흰 스타렉스에서 내가 내리지

Kotlin 컬렉션 본문

Kotlin

Kotlin 컬렉션

주씨. 2023. 9. 8. 22:38
728x90

코틀린 컬렉션 타입은 기본적으로 네 가지로 분류할 수 있다. 

배열, 이터러블, 시퀀스, 맵 이다. 

 

# 이터러블

fun main(){
    val list = listOf("red", "green", "blue")

    for (item in list){
        print(item + " ")
    }
}

 

 

# 컬렉션, 리스트, 집합

- 리스트는 인덱스를 통한 원소 접근이 가능한, 순서가 정해진 원소의 컬렉션이다. 

일반적인 리스트 구현은 인덱스를 통한 임의 접근이 가능한 ArrayList와 원소를 빠르게 추가하거나 삭제할 수 있지만, 인덱스로 원소에 접근할 때는 선형 시간이 걸리는 LinkedList가 있다. 

 

- 집합은 유일한 원소들로 이뤄진 컬렉션이다. 원소의 순서는 구현에 따라 다르다.

- HashSet은 해시 테이블이 기반인 구현이며, 원소의 해시 코드에 따라 원소 순서가 정해진다. 일반적으로 이 순서는 원소타입의 hashCode() 메서드 구현에 따라 달라지므로, 예측하기 어렵다. 

- LinkedHashSet은 해시 테이블이 기반이지만 삽입 순서를 유지하기 때문에 원소를 이터레이션하면 집합에 삽입된 순서대로 원소를 순회할 수 있다. 

- TreeSet은 이진 탐색 트리가 기반이며, 어떤 비교 규칙에 따라 일관성 있는 원소 순서를 제공한다. 

 

 

# Comparable과 Comparator

자바처럼 코틀린도 Comparable과 Comparator 타입을 지원하며, 몇몇 컬렉션 연산에 이를 활용한다.

비교 가능(comparable) 인스턴스는 자연적인 순서(natural order)를 지원하며, 이런 타입의 인스턴스들은 모두 동일한 타입의 다른 인스턴스와 순서를 비교할 떄 쓸 수 있는 compareTo() 메서드를 포함한다.

 

만약 Person 클래스에 전체 이름을 바탕으로 자연스러운 순서를 부여하고 싶다고 한다면, 

class Person(
    val firstName: String,
    val familyName: String,
    val age: Int
): Comparable<Person>{
    val fullName get() = "$firstName $familyName"
    override fun compareTo(other: Person) = fullName.compareTo(other.fullName)
}

compareTo() 구현은 equals() 함수 구현과 서로 의미가 일치해야 한다. 

 

 

 

# 컬렉션 생성하기

import java.util.TreeMap

fun main(){
    val list = ArrayList<String>()
    list.add("red")
    list.add("green")
    println(list)   // [red, green]

    val set = HashSet<Int>()
    set.add(12)
    set.add(21)
    set.add(12)
    println(set)    // [12, 21]

    val map = TreeMap<Int, String>()
    map[20] = "Twenty"
    map[10] = "Ten"
    println(map)    // {10=Ten, 20=Twenty}
}

 

 

  • emptyList() / emptySet()
    • 불변인 빈 리스트/ 집합 인스턴스를 생성한다.
  • listOf() / setOf()
    • 인자로 제공한 배열에(가변 길이 인자)에 기반한 불변 리스트/집합 인스턴스를 만든다
  • listOfNotNull()
    • 널인 값을 걸러내고 남은 원소들로 이뤄진 새 불변 리스트를 만든다
  • mutableListOf() / mutableSetOf()
    • 가변 리스트/집합의 디폴트 구현 인스턴스를 만든다 
    • 내부적으로 ArrayList와 LinkedHashSet을 사용한다
  • arrayListOf()
    • 새로운 ArrayList를 만든다.
  • hashSetOf() / linkedSetOf() / sortedSetOf()
    • HashSet / LinkedHashSet / TreeSet 의 새 인스턴스를 만든다

 

 

# forEach() 확장함수

fun main(){
    intArrayOf(1, 2, 3).forEach { print(it*it) }    //  149
    listOf("a", "b", "c").forEach{print("'$it'")}   // 'a''b''c'
    sequenceOf("a", "b", "c").forEach { print("'$it'") }    // 'a''b''c'
    mapOf(1 to "one", 2 to "two", 3 to "three").forEach{
        (key, value) -> print("$key -> $value")     // 1 -> one2 -> two3 -> three
    }
    
    // 원소 인덱스를 참조해야 한다면 forEachIndexed() 함수를 쓰면 된다.
    listOf(10, 20, 30).forEachIndexed{i, n -> println("$i: ${n*n}")}    //0: 100  1: 400  2: 900
}

 

 

# 변환 

컬렉션의 모든 원소를 주어진 규칙에 따라 변경한 다음, 이를 정해진 방식으로 조합해서 새로운 컬렉션을 만들어내는 변환 함수를 제공한다.

이런 함수는 매핑(mapping), 평평하게 하기(flattening), 연관 짓기(association) 라는 세 가지 유형으로 나눌 수 있다.

 

1. map

주어진 함수를 원본 컬렉션의 각 원소에 적용한다. 

그리고 함수를 적용한 결과는 새로운 컬렉션의 원소가 된다. 

fun main(){
    println(setOf("red", "green", "blue").map{it.length})       // [3, 5, 4]
    println(listOf(1, 2, 3, 4).map{it * it})                    // [1, 4, 9, 16]
    println(byteArrayOf(10, 20, 30).map{it.toString(16)})   // [a, 14, 1e]

    println(
        arrayOf("1", "red", "2", "green", "3").mapNotNull { it.toIntOrNull() }
    )       // [1, 2, 3]
}

 

2. flat

평평하게 하는 연산은 원래 컬렉션의 각 원소를 컬렉션으로 변환한 다음, 각 컬렉션을 차례로 이어 붙여서 한 컬렉션으로 합쳐준다.

flatMap() 함수를 통해 이런 변환을 구현할 수 있다. 

fun main(){
    // [a, b, c, d, e, f, h, h, i]
    println(setOf("abc", "def", "ghi").flatMap{it.asIterable()})

    // [1, 2, 3, 4, 5]
    println(listOf(listOf(1, 2), setOf(3, 4), listOf(5)).flatten())
}

'Kotlin' 카테고리의 다른 글

마이크로서비스 구축  (0) 2023.09.09
Enum Class, Data Class, Inline Class  (1) 2023.09.08
backing field  (1) 2023.09.08
Kotlin 기초  (4) 2023.09.05