프로그래밍 노트/Kotlin

[Kotlin] 컬렉션과 범위에서 사용할 수 있는 관례 정리

깡냉쓰 2023. 6. 29. 14:46
728x90
반응형

인덱스로 원소에 접근 - Map 원소 접근시 괄호([]) 사용

  • 코틀린에서는 맵의 원소에 접근할 때 자바에서 배열 원소에 접근하는 각 괄호([])를 사용할 수 있다.
  • 인덱스 연산자는 get/set 관례를 따르며, Map과 MutableMap 인터페이스에는 이미 두 메서드가 들어가 있다.
val value = map[key]
mutableMap[key] = newValue
  • 구현 예시
operator fun Point.get(index: Int): Int {
  return when(index) {
    0 -> x
    1 -> y
    else ->
      throw IndexOutOfBoundsException("Invalid coordinate $index")
  }
}

val p = Point(10, 20)
println(p[1])
>> 20

in 관례 - contains(원소 포함 여부) 사용

  • in은 객체가 컬렉션에 들어가있는지 검사한다. in 연산자와 대응하는 함수는 contains 이다.
data class Rectangle(val upperLeft: Point, val lowerRight: Point)
operator fun Rectangle.contains(p: Point): Boolean {
  return p.x in upperLeft.x until lowerRight.x &&
    p.y in upperLeft.y until lowerRight.y
}

val rect = Rectangle(Point(10, 20), Point(50, 50))
println(Point(20, 30) in rect)
>> true
println(Point(5, 5) in rect)
>> false

a in c -> c.contains(a)

rangeTo 관례 - ... 연산자(범위) 사용

  • 1..10은 1부터 10까지 모든 수가 들어있는 범위를 가리킨다.
  • .. 연산자는 rangeTo 함수를 간략하게 표현한 방법이다.
  • 코틀린 표준 라이브러리에는 모든 Comparable객체에 대해 적용 가능한 rangeTo 함수가 들어있다.
// 범위를 반환하며, 어떤 원소가 그 범위 안에 들어있는지 in을 통해 검사할 수 있다.
operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T>

start..end == start.rangeTo(end)
// 날짜 범위 다루기
val now = LocalDate.now()
val vacation = now..now.plusDays(10)
now.plusWeeks(1) in vacation
>> true

now..now.plusDays(10) -> now.rangeTo(now.plusDays(10))
  • 범위 연산자는 우선순위가 낮아 범위를 괄호로 둘러싸야 한다.
(0..n)forEach { print(it) }

iterator 관례 - for(element in list) 사용

  • for (x in list) { … } 와 같은 문장은 list.iterator()호출해서 이터레이터를 얻은 다음 hasNext(), next() 호출이 반복되는 식으로 변환된다.
  • 컬렉션이 지원하는 in 연산자와는 다르다.
operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> = 
  // object 익명객체 (LocalDate원소에 대한 Iterator 구현)
  object: Iterator<LocalDate> {
    var current = start
    override fun hasNext() = current <= endInclusive
    override fun next() = current.apply {
      // 현재 날짜를 저장한 다음에 날짜를 변경 후 반환한다.
      current = plusDays(1)
    }
  }
}

val newYear = LocalDate.ofYearDay(2017, 1)
val daysOff = newYear.minusDays(1)..newYear
for (dayOff in daysOff) { println(dayOff) }
  • ClosedRange<LocalDate>에 대한 확장 함수 iterator를 정의했기 때문에 LocalDate의 범위 객체를 for 루프에 사용할 수 있다.
728x90
반응형