본문 바로가기

Study/Kotlin Study

[Kotlin] 컬렉션 유틸리티

+ 항공대학교 김철기 교수님의 객체 지향 프로그래밍 과목 내용를 정리한 글입니다.

 

++ 직접 코딩하라는 문제는 나오지 않고, 코드를 주고 어떤 의미인지 적는 문제가 출제됩니다.

Collection의 생성

fun main() {
    val a1 = listOf(1, 2, 3) // unmutable list 생성
    println(a1) // [1, 2, 3]
    // a1.add(4) 불가능

    val a2 = mutableListOf(1, 2, 3) // mutable list 생성
    a2.add(4) // 가능
    println(a2) // [1, 2, 3, 4]

    val m1 = mapOf(1 to "I", 5 to "V", 10 to "X", Pair(50, "L")) // pair 객체를 통해 map 생성
    println(m1) // {1=I, 5=V, 10=X, 50=L}
    // m1.add(2 to "II") 불가능

    val m2 = mutableMapOf(1 to "I", 5 to "V", 10 to "X", Pair(50, "L"))
    m2[2] = "II"
    m2.remove(5)
    println(m2) // {1=I, 10=X, 50=L, 2=II}
}

 


Sequence

요청하면 값을 뒤늦게 나열하는 객체이다. (일종의 프로그램 흐름)

 

generateSequencce(초기값) { 이전 값에서 다음 값을 생성하는 함수 }

=> null이 반환되면 생성이 종료된다. (null이 반환되지 않으면 무한히 생성)

 

fun main() {
    val seq = sequence {
        yield(0)
        yieldAll(listOf(1, 2, 3))
        yieldAll(intArrayOf(4, 5, 6).iterator()) // Array는 컬렉션이 아니기 때문에 iterator() 사용
        yieldAll(generateSequence(10) { if(it < 50) it * 3 else null}) // [10, 30, 90]
    }

    var idx = 0
    for (elem in seq) {
        println("$idx: $elem")
        idx ++
    }
}

Collection 간의 변환

Collection 간 변환을 위한 다양한 함수를 제공한다.

fun main() {
    val a1 = listOf(1, 2, 3, 2, 3).toSet()
    println(a1) // [1, 2, 3] (중복 제거)

    val a2 = arrayOf("red", "green", "blue").toSortedSet()
    println(a2) // [blue, green, red] (사전 순 정렬)

    val a3 = mapOf(1 to "One", 2 to "Two", 3 to "Three").toList()
    println(a3) // [(1, One), (2, Two), (3, Three)] (Key - Value 쌍을 Pair로 변환)

    val a4 = sequenceOf(1 to "One", 2 to "Two", 3 to "Three").toMap()
    println(a4) // {1=One, 2=Two, 3=Three} (Pair을 Key - Value 쌍으로 변환)
}

 


iterator()와 for 문

Array 및 모든 Collection과 Map은 iterator() 함수가 있으면 for문에 사용이 가능하다.

- Map의 경우 Key와 Value의 쌍이 Map.Entry 객체로 반환된다. (구조 분해를 이용해 쉽게 이용 가능)

 

< 구조 분해를 사용하지 않은 코드 >

fun main() {
    val map = mapOf(1 to "One", 2 to "Two", 3 to "Three")

    for(elem in map) {
        println("${elem.key} -> ${elem.value}")
    }
}

 

< 구조 분해를 사용한 코드 >

fun main() {
    val map = mapOf(1 to "One", 2 to "Two", 3 to "Three")

    for((key, value) in map) {
        println("${key} -> ${value}")
    }
}

 

< forEach문을 사용한 코드 >

fun main() {
    val map = mapOf(1 to "One", 2 to "Two", 3 to "Three")

    map.forEach { println("${it.key} -> ${it.value}") }
}

 

< 람다 함수의 파라미터 지정을 이용한 코드 >

fun main() {
    val map = mapOf(1 to "One", 2 to "Two", 3 to "Three")

    map.forEach { k, v -> println("${k} -> ${v}") }
}

 

< forEachIndexed문을 사용한 코드 >

인덱스를 다룰 때 매우 편하여 자주 사용한다..

fun main() {
    val arr = intArrayOf(1, 2, 3)

    arr.forEachIndexed { idx, value -> println("$idx -> $value") }
}

Collection의 유틸리티

< List에 대한 유틸리티 1 >

fun main() {
    val list = listOf(1, 2, 3)

    println(list.isEmpty()) // false (list가 비지 않았으므로)

    println(list.size) // 3

    println(list.contains(4)) // false (list에 4라는 원소가 없으므로)
    println(2 in list) // true (contains와 같음)
    println(list.containsAll(listOf(1, 2))) // true (1, 2가 모두 존재하므로)

    val l2 = list + 4 // 원소를 추가한 새로운 리스트를 반환 (list에 직접 추가는 불가)
    println(l2) // [1, 2, 3, 4]

    val l3 = list - setOf(2, 5)
    println(l3) // [1, 3] (5는 없으므로 2만 제거되어 생성)
}

 

< List에 대한 유틸리티 2 - 인덱스 이용>

fun main() {
    val list = listOf(1, 4, 6, 2, 4, 1, 6)

    println(list.get(3)) // 2
    println(list[3]) // 2
    // list[10] OutOfIndex 주의!
    println(list.getOrNull(10)) // null (인덱스 범위를 벗어나면 null 반환)

    println(list.indexOf(4)) // 1 (원소 4의 처음 등장하는 인덱스 반환)
    println(list.lastIndexOf(4)) // 4 (원소 4의 마지막으로 등장하는 인덱스 반환)
    println(list.indexOf(8)) // -1 (list에 없는 원소의 인덱스는 -1 반환)
}

 

< ArrayList에 관한 유틸리티 1 >

fun main() {
    val list = arrayListOf(1, 2, 3)

    list.add(4)
    println(list) // [1, 2, 3, 4]

    list.remove(3)
    println(list) // [1, 2, 4]

    list.addAll(setOf(5, 6))
    println(list) // [1, 2, 4, 5, 6]

    list.removeAll(listOf(1, 2))
    println(list) // [4, 5, 6]

    list.retainAll(listOf(5, 6, 7)) // [5, 6, 7] 안에 있는 원소만 남도록
    println(list) // [5, 6]

    list += 4
    println(list) // [5, 6, 4] (맨 뒤에 4 추가)

    list -= 6
    println(list) // [5, 4] (원소 6 제거)

    list += setOf(8, 9)
    println(list) // [5, 4, 8, 9]

    list -= listOf(7, 8)
    println(list) // [5, 4, 9]

    list.clear()
    println(list) // []
}

 

< ArrayList에 관한 유틸리티 2 >

fun main() {
    val list = arrayListOf(1, 4, 6, 2, 4, 1, 7)

    list[3] = 0 // 인덱스 3에 해당하는 원소를 0으로 교체
    list.set(2, 1) // 인덱스 2에 해당하는 원소를 1으로 교체
    println(list) // [1, 4, 1, 0, 4, 1, 7]

    list.add(3, 8) // 인덱스 3에 원소 8 추가
    println(list) // [1, 4, 1, 8, 0, 4, 1, 7] (한 칸씩 밀림)

    val segment = list.subList(2, 5) // 2 ~ 4 까지의 원소를 추출하여 서로 연동된 sublist 구성
    println(segment) // [1, 8, 0]
    list[3] = 0
    println(list) // [1, 4, 1, 0, 0, 4, 1, 7]
    println(segment) // [1, 0, 0] (list가 변경될 시 sublist도 변경)
    segment[1] = 8
    println(list) // [1, 4, 1, 8, 0, 4, 1, 7]
    println(segment) // [1, 8, 0] (sublist가 변경될 시 list도 변경)
}

'Study > Kotlin Study' 카테고리의 다른 글

[Kotlin] 제네릭스  (0) 2023.11.28
[Kotlin] 파일과 I/O 스트림  (3) 2023.11.27
[Kotlin] 컬렉션 타입  (0) 2023.11.20
[Kotlin] 봉인된 클래스  (1) 2023.11.14
[Kotlin] 부호 없는 정수  (0) 2023.11.14