HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/Kotlin/
콜렉션

콜렉션

코틀린이 제공해주는 콜렉션의 진화는 두 가지. 함수 확장과 뷰
뷰페어와 트리플 사용하기객체 배열과 프리미티브 배열리스트 사용하기immutable viewmutable viewlist to mapSet 사용Map 사용

뷰

  • Java의 대부분의 콜렉션은 뮤터블임. 하지만 최근 몇년간 Java는 이뮤터블 콜렉션을 선보였지만, 같은 인터페이스를 구현하고 있다는 문제점을 갖고 있음 → Runtime에 UnsupportedOperationException이 나옴
  • 이와 달리 코틀린은 연산이 불가능하다는 것을 실행 시간이 되어서야 알리지 않음 → 그래서 뷰가 존재
    • 리스트, 셋, 맵은 각기 뷰를 두 가지씩 갖고 있음. read-only view로 통하는 immutable view, read-write view로 불리기도 하는 mutable view
    • 예로 List(read-only)와 MutableList(read-write view)는 코틀린의 ArrayList 뷰임
    • 주의사항 : 읽기전용 뷰가 thread safety를 제공해 준다고 가정 x. 읽기 전용 뷰가 참조하는 콜렉션은 뮤터블 콜렉션임. 다른 스레드가 해당 콜렉션을 변경할 수도 있음

페어와 트리플 사용하기

println(Pair("Tom", "Jerry")) // (Tom, Jerry) println(mapOf("Tom" to "Cat", "Jerry" to "Mouse")) // {Tom=Cat, Jerry=Mouse}
  • 첫번째 줄은 Pair의 생성자를 이용해서 인스턴스 생성
  • 두번째 줄은 to() 확장함수를 이용해 Map의 엔트리가 될 페어를 만듦. to() 확장함수는 코틀린의 모든 객체에서 사용이 가능

객체 배열과 프리미티브 배열

  • Array<T> 클래스는 코틀린의 배열을 상징함. 배열은 낮은 수준의 최적화가 필요할 때만 사용하도록 하고, 그 외에는 List 같은 다른 자료구조 사용하기
val frineds = arrayOf("Tintin", "Snowy", "Haddock", "Calculus") println(friends::class) // class kotlin.Array println(friends.javaClass) // class [Ljava.lang.String; val numbers = arrayOf(1, 2, 3) println(numbers::class) // class kotlin.Array println(numbers.javaClass) // class [Ljava.lang.Integer; // Integer 배열이 아닌 int 배열을 만들기 위해서는 intArrayOf() 메서드를 사용 val numbers = intArrayOf(1, 2, 3) println(numbers::class) println(numbers.javaClass) // class [I // Array의 생성자는 파라미터로 // 1. 배열의 사이즈 // 2. 0부터 시작하는 인덱스를 받아 해당 위치에 있는 값을 리턴해주는 함수 // 를 받음 prinrtln(Array(5) { i -> (i + 1) * (i + 1) }.sum()) // 55
 

리스트 사용하기

immutable view

val fruits: List<String> = listOf("Apple", "Banana", "Grape") println(fruits) // [Apple, Banana, Grape] println("first's ${fruits[0]}, that's ${fruits.get(0)}") // first's Apple, that's Apple
  • 인덱스 연산자를 사용하는 편이 get() 보다 노이즈가 적고 편리하다. get() 대신 []를 사용하기
  • collection에 대해서 값이 있는지 없는지 확인하기 위해서는 contains() 메서드를 사용하거나 in 연산자를 사용할 수 있다.
    • println(fruits.contains("Apple")) // true println("Apple" in fruits) // true
    • in 을 사용하는 게 더 표현력이 좋고 직관성이 있다.
val fruits: List<String> = listOf("Apple", "Banana", "Grape") println(fruits::class) // class java.util.Arrays$ArrayList println(fruits.javaClass) // class java.util.Arrays$ArrayList fruits.add("Celery") //inferunit.kts:7:8: error: unresolved reference 'add'. // + 와 - 연산자로 해당 리스트에서 요소를 추가, 제외하고 새로운 리스트를 만들 수 있음 val fruits2 = fruits + "Orange" println(fruits) //[Apple, Banana, Grape] println(fruits2) // [Apple, Banana, Grape, Orange] val noBanana = fruits - "Banana" println(noBanana) // [Apple, Grape]

mutable view

val fruits: MutableList<String> = mutableListOf("Apple", "Banana", "Grape") fruits.add("Orange")
  • mutableList는 변경이 가능함
  • 가능한 mutableListOf() 보다는 listOf() 를 사용하자. 변경 가능 객체는 좋지 않다.
  • 뮤터블 리스트를 만들어야 겠다는 생각이 든다면 당장 주변에 도움의 손길을 요청하라. 그러면 분명 뮤터블 리스트를 만들지 말라고 할 것이다. 충분한 생각과 의논이 끝난 후에도 뮤터블 리스트를 만드는 것이 올바른 선택이라는 판단이 든다면 mutableListOf() 함수를 이용해서 리스트를 만들 수 있다.

list to map

// associate val list = listOf("apple", "banana", "cherry") val map = list.associate { it to it.length } // 키: 요소, 값: 요소의 길이 println(map) // {apple=5, banana=6, cherry=6} // associateBy val list = listOf("apple", "banana", "cherry") val map = list.associateBy { it.first() } // 키: 첫 글자, 값: 요소 println(map) // {a=apple, b=banana, c=cherry} // associateWith val list = listOf("apple", "banana", "cherry") val map = list.associateWith { it.length } // 키: 요소, 값: 요소의 길이 println(map) // {apple=5, banana=6, cherry=6}

Set 사용

  • setOf() → Set<T>인스턴스
  • mutableSetOf() → MutableSet<T>
  • hashSetOf() → java.util.HashSet<T>
  • linkedSetOf() → LinkedHashSet
  • sortedSetOf() → TreeSet
List<T> 처럼 Set<T>와 MutableSet<T>에는 +, -, contains, in 등 많은 함수들이 있음

Map 사용

  • mapOf() → Map<K, V >의 읽기전용 맵
  • mutableMapOf() → MutableMap<K, V>
  • hashMapOf()
  • linkedMapOf()
  • sortedMapOf()