Yebali

Kotlin의 Collections 본문

Kotlin

Kotlin의 Collections

예발이 2021. 10. 31. 23:33

Kotlin의 Collection들이 지원하는 다양한 함수들을 알아보자.

List

List는 순서가 있는 선형 자료구조이다.

Kotlin에서는 수정이 가능한 MutableList와 수정이 불가능한 List가 있다.

fun main() {
    val l1 = mutableListOf<Int>() // MutableList 생성
    val l2 = listOf<Int>() // List 생성
    
    l1.add(1) // mutableList는 수정이 가능하다.
    l1.remove(1)
    
    //l2.add(2) // List는 수정을 할 수 없다.
}

Set

Set은 순서가 없는 자료구조로써 중복을 허용하지 않는다.

중복을 허용하지 않기 때문에 동일한 원소를 여러 번 넣어도 Set 내에는 1개만 존재하게 된다

Kotlin에서는 수정이 가능한 MutableSet과 수정이 불가능한 Set이 있다.

fun main() {
    val s1 = mutableSetOf<Int>()
    val s2 = setOf<Int>()

    s1.add(1)
    s1.add(1)

    println("s1.size = ${s1.size}") // s1.size = 1이 출력됨.

    //s2.add(2) 추가가 불가능하다.
}

Map

Map은 Key-Value 쌍을 이루는 데이터를 저장하는 자료구조이다.

Key는 중복될 수 없으며, 동일한 Key로 원소 추가 시 Value는 덮어씌워진다.

Kotlin에서는 수정이 가능한 MutableMap과 수정이 불가능한 Map이 있다.

fun main() {
    val m1 = mutableMapOf(1 to 100, 2 to 100, 3 to 100)
    val m2 = mapOf(3 to 300, 4 to 400)

    m1.put(5, 500)
    println("m1 = ${m1}") // m1 = {1=100, 2=100, 3=100, 5=500} 출력.

    // m2.put(5, 500) 추가가 불가능하다.
}

 

참고로 Map의 원소들은 [] 연산자를 통해 접근할 수 있다.

val map = mapOf("key" to 42)

val value1 = map["key"]
val value2 = map["key2"]

val value3: Int = map.getValue("key")

Collection의 다양한 함수들

Collection에서 사용할 수 있는 유용한 함수들…

filter

Collection 내 원소들 중 특정 조건에 맞는 원소들만 Collection으로 만들어 반환해준다.

val numbers = listOf(1, -2, 3, -4, 5, -6)     

val positives = numbers.filter { x -> x > 0 }  
val negatives = numbers.filter { it < 0 }      

val s1 = setOf(1, -2, 3, -4, 5)

val pos = s1.filter { x -> x > 0 } // java.util.ArrayList가 반환.
val neg = s1.filter { it < 0 }

val map = mapOf(3 to 300, 4 to 400)
val filteredMap = map.filter { it.key < 3 } java.util.LinkedHashMap 반환

map

위에서 본 Collection Map과는 다른 함수 map이다.

모든 원소에 대해 특정 연산을 하여 Collection을 반환해준다.

val list = listOf(1, -2, 3, -4, 5, -6)
val list_double = list.map { it * 2 } // [2, -4, 6, -8, 10, -12]

val set = setOf(1, -2, 3, -4, 5, -6)
val set_double = set.map { x -> x * 2 } // [2, -4, 6, -8, 10, -12]

val map = mapOf(1 to 100, -2 to -200, 3 to 300, -4 to -400)
val map_double = map.map { it.key * 2 to it.value * 2 } // [(2, 200), (-4, -400), (6, 600), (-8, -800)]

any, all, none

특정 조건을 만족하는 원소가 있는지 여부를 확인하는 함수이다.

  • any : 조건을 만족하는 원소가 하나라도 있으면 true / 없으면 false
  • all : 모든 원소가 조건을 만족하면 true / 아니면 false
  • none : 모든 원소가 조건을 만족하지 않으면 true / 아니면 false
val list = listOf(1, -2, 3, -4, 5, -6)

val any = list.any { it < 2 }

val all = list.all { it < 3 }

val none = list.none { x -> x > 2 }

find, findLast

특정 조건을 만족하는 원소를 찾는 함수이다.

  • find : 조건을 만족하는 첫 번째 원소를 반환.
  • findLast : 조건을 만족하는 마지막 원소를 반환
val words = listOf("Lets", "find", "something", "in", "collection", "somehow")  

val first = words.find { it.startsWith("some") }    // somethinig 
val last = words.findLast { it.startsWith("some") } // somehow

val nothing = words.find { it.contains("nothing") }  // null

first, last + OrNull

Collection의 첫 번째, 또는 마지막 원소를 반환한다.

조건을 넣을 경우 find, findLast처럼 사용할 수 있다.

firstOrNull, lastOrNull은 해당 원소가 없으면 null을 반환한다.

val numbers = listOf(1, -2, 3, -4, 5, -6)

val first = numbers.first()   // 1
val last = numbers.last()     // -6

val firstEven = numbers.first { it % 2 == 0 }  // -2
val lastOdd = numbers.last { it % 2 != 0 }     // 5

val firstOrNull = numbers.firstOrNull { it > 7 } // null

count

Collection의 원소들의 개수를 반환한다.

조건을 넣을 경우 해당 조건에 맞는 원소들의 개수를 반환한다.

val numbers = listOf(1, -2, 3, -4, 5, -6)

val totalCount = numbers.count()               // 6
val evenCount = numbers.count { it % 2 == 0 }  // 3

associateBy, groupBy

Collection의 원소들로부터 Map을 만드는 함수이다.

  • associateBy : 동일한 Key가 있는 경우 마지막 원소의 값을 Value로 넣는다.
  • groupBy : 동일한 key가 있는 경우 모든 값을 Value로(List안에 넣어서 Value로 만듦) 넣는다.
fun main() {
    data class Person(val name: String, val city: String, val phone: String) 

    val people = listOf(
        Person("John", "Boston", "+1-888-123456"),
        Person("Sarah", "Munich", "+49-777-789123"),
        Person("Svyatoslav", "Saint-Petersburg", "+7-999-456789"),
        Person("Vasilisa", "Saint-Petersburg", "+7-999-123456"))

    val phoneBook = people.associateBy { it.phone }
    val cityBook = people.associateBy(Person::phone, Person::city)
    val peopleCities = people.groupBy(Person::city, Person::name) 
    val lastPersonCity = people.associateBy(Person::city, Person::name) 
}
phoneBook = {+1-888-123456=Person(name=John, city=Boston, phone=+1-888-123456),
            +49-777-789123=Person(name=Sarah, city=Munich, phone=+49-777-789123),
            +7-999-456789=Person(name=Svyatoslav, city=Saint-Petersburg, phone=+7-999-456789),
            +7-999-123456=Person(name=Vasilisa, city=Saint-Petersburg, phone=+7-999-123456)}
            
cityBook = {+1-888-123456=Boston, 
          +49-777-789123=Munich,
          +7-999-456789=Saint-Petersburg,
          +7-999-123456=Saint-Petersburg}
          
peopleCities = {Boston=[John], Munich=[Sarah], Saint-Petersburg=[Svyatoslav, Vasilisa]}

lastPersonCity = {Boston=John, Munich=Sarah, Saint-Petersburg=Vasilisa}

partition

Collection을 조건에 맞는 Collection과 조건에 맞지 않는 Collection으로 나누는 함수.

나누어진 Collection은 Pair에 담겨 반환된다.

val numbers = listOf(1, -2, 3, -4, 5, -6) 

val evenOdd = numbers.partition { it % 2 == 0 } 
val (positives, negatives) = numbers.partition { it > 0 } // ([1, 3, 5], [-2, -4, -6])

flatMap

각 Collection의 원소들을 하나의 Collection으로 변환해주는 함수.

val fruitsBag = listOf("apple","orange","banana","grapes") 
val clothesBag = listOf("shirts","pants","jeans")          
 
val cart = listOf(fruitsBag, clothesBag) // [[apple, orange, banana, grapes], [shirts, pants, jeans]]
val mapBag = cart.map { it }             // [[apple, orange, banana, grapes], [shirts, pants, jeans]]
val flatMapBag = cart.flatMap { it }     // [apple, orange, banana, grapes, shirts, pants, jeans]

minOrNull, MaxOrNull

Collection내에서 최소 값이나 최대 값을 반환해주는 함수.

값이 없다면 null을 반환한다.

val numbers = listOf(1, 2, 3)
val empty = emptyList<Int>()
val only = listOf(3)

println("Numbers: $numbers, min = ${numbers.minOrNull()} max = ${numbers.maxOrNull()}") 
println("Empty: $empty, min = ${empty.minOrNull()}, max = ${empty.maxOrNull()}")        
println("Only: $only, min = ${only.minOrNull()}, max = ${only.maxOrNull()}")

sorted

Collection을 정렬하는 함수.

기본적으로 오름차순이며, sortedDescending()을 사용하면 내림차순으로 정렬이 가능하다.

val shuffled = listOf(5, 4, 2, 1, 3, -10)                   // 1
val natural = shuffled.sorted()                             // [-10, 1, 2, 3, 4, 5]
val inverted = shuffled.sortedBy { -it }                    // [5, 4, 3, 2, 1, -10]
val descending = shuffled.sortedDescending()                // [5, 4, 3, 2, 1, -10]
val descendingBy = shuffled.sortedByDescending { abs(it)  } // [-10, 5, 4, 3, 2, 1]

zip

두 개의 Collection을 병합하여 새로운 Collection을 만드는 함수.

val A = listOf("a", "b", "c")
val B = listOf(1, 2, 3, 4)

val resultPairs = A zip B                      // A to B : [(a, 1), (b, 2), (c, 3)]
val resultReduce = A.zip(B) { a, b -> "$a$b" } // $A$B : [a1, b2, c3]

getOrElse

Collection의 원소에 안전하게 접근하기 위한 함수.

index에 값이 있으면 해당 값을 반환하고, 없으면 ‘{}’ 안의 default 값을 반환

val list = listOf(0, 10, 20)
println(list.getOrElse(1) { 42 })    //  10
println(list.getOrElse(10) { 42 })   //  42

val map = mutableMapOf<String, Int?>()
println(map.getOrElse("x") { 1 })   // 1

map["x"] = 3
println(map.getOrElse("x") { 1 })   // 3

map["x"] = null
println(map.getOrElse("x") { 1 })   // 1

 

'Kotlin' 카테고리의 다른 글

Java, Kotlin의 날짜와 시간  (0) 2022.11.28
Spring JPA Entity에 Data Class를 사용해도 될까?  (0) 2021.10.31
Kotlin의 Data/Enum 클래스  (0) 2021.09.22
Kotlin의 nullable변수 처리  (0) 2021.09.22
Kotlin의 제너릭  (0) 2021.09.22