Kotlin 콜랙션(Collection)


Java에는 컬렉션 프레임워크가 있는 것처럼 Kotlin에도 컬렉션 프레임워크가 있다. Kotlin의 컬렉션 프레임워크는 읽기만(read-only,immutable) 가능한 컬렉션과 읽기/쓰기(mutable, read/write)가 가능한 컬렉션이 있다.

대표적인 요서만 살펴 보도로 하겠다.

Collection & MutableCollection

kotlin.collection.Collection 인터페이스이다.

interface Collection<out E> : Iterable<E>

E는 Collection의 요소이다. 이 인터페이스는 읽기만 지원한다.

읽기/쓰기는 MutableCollection 인터페이스에서 지원한다.

interface MutableCollection<E> : Collection<E>, MutableIterable<E>

ECollection의 요소아다.

List & MutableList

List 인터페이스는 Collection 인터페이스를 상속하고 있다.

interface List<out E> : Collection<E>

ECollection의 요소이다. 이 인터페이스는 List의 읽기만 지원한다.

읽고 쓰기는 MutableList 인터페이스에서 지원한다.

interface MutableList<E> : List<E>, MutableCollection<E>

E는 컬렉션의 요소. 요소 추가/삭제 기능을 제공하는 인터페이스.

Map & MutableMap

Map은 키와 값의 쌍으로 처리한다. Map은 읽기만 지원하는 인터페이스이다.

interface Map<K, out V>

MutableMap은 요소의 추가 및 삭제 처리를 제공한다.

interface MutableMap<K, V> : Map<K, V>

간단한 예로 읽기만 가능한 Map를 만들어 보도로 하겠다.

fun main() {
    var map = mapOf("Red" to "#f00", "Green" to "#0f0", "Blue" to "#00f")

    println(map["Red"])

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

Output:

#f00
Red = #f00
Green = #0f0
Blue = #00f

Set & MutableSet

Set는 목록과 비슷하지만 중복 값을 허용하지 않는 점이 다르고 순서가 없다. Set은 읽기만 지원하는 인터페이스이다.

interface Set<out E> : Collection<E>

MutableSet은 요소의 추가 및 삭제 처리를 제공한다.

interface MutableSet<E> : Set<E>, MutableCollection<E>

간단한 예로 변경이 가능한 Set를 만들어 보도로 하겠다.

fun main() {
    var s = mutableSetOf("Red", "Green", "Blue")

    s.add("Red")

    println(s)
}

Output:

[Red, Green, Blue]

배열 및 목록 생성

배열은 Array 클래스으로 인스턴스를 생성한다. 다음과 같은 형식으로 배열을 만든다.

Array<타입명>(요수 갯수) {초기 처리}

List<타입명>(요수 갯수) {초기 처리}

간단한 구현 예제를 보도록 하겠다.

fun main() {
    val evenNumbers = Array(10) { it * 2 }

    for (n in evenNumbers) {
        println(n)
    }
}

Output:

0
2
4
6
8
10
12
14
16
18

위 예제는 짝수를 선언하고 있다.

생성 표준 라이브러리

array, listOf, arrayListOf, linkedListOf 배열 및 목록 선언은 코틀린 표준 라이브러리로 다음 함수를 제공한다.

  • arrayOf
    • Array 인스턴스를 간편하게 생성한다.
  • listOf:
    • java.util.List를 생성한다.
    • 요소를 변경할 수 없다.
  • arrayListOf
    • java.util.ArrayList 인스턴스를 생성한다.
    • Java와 마찬가지로 추가, 삭제 등이 가능하다.
  • linkedListOf
    • java.util.LinkedList 인스턴스를 생성한다.
    • Java와 마찬가지로 추가, 삭제 등이 가능하다.
val oddNumbers = arrayOf(1, 3, 5, 7, 9)
val list = listOf(1,2,3,4,5)
val arrayList = arrayListOf(1,2,3,4,5)
val linkedList = linkedListOf(1,2,3,4,5)

배열(Array)

arrayOf()으로 배열을 생성한다. 배열의 개수가 고정이긴 하지만 성능이 우수하다.

var nums = arrayOf(1, 2, 3)
var cols = arrayOf("Red", "Green", "Blue")

for (n in nums) { println(n) }
for (c in cols) { println(c) }

[...]는 배열의 요소에 액세스한다. 배열의 인덱스는 0부터 시작한다.

println(nums[0])
println(cols[1])

목록(List)

listOf()으로 목록을 생성한다. 배열 개수 고정인데 비해 목록은 .add().remove()으로 추가 삭제할 수 있다. 그러나 배열은 nums[1] = 123으로 값을 변경할 수 있지만, 목록은 nums[1] = 222으로 값을 변경할 수 없다.

var nums = listOf(1, 2, 3)
var cols = listOf("Red", "Green", "Blue")

for (n in nums) { println(n) }
for (c in cols) { println(c) }

아래와 같이 목록에 필터를 걸어 짝수인 조건에 일치하는 요소를 추출할 수 있다.

val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(nums.filter { it % 2 == 0 })   // [2, 4, 6, 8, 10]

목록 주요 함수

forEach 함수

forEach 함수는 목록에 반복 처리를 할 수 있다.

fun main() {
    val array = arrayOf(1, 2, 3, 4, 5)

    // lambda으로 사용한 방법이다.
    array.forEach({ element ->
        print("$element,")
    }) // => 1,2,3,4,5
    println()

    // 괄호'()'은 생략할 수 있다.
    array.forEach { element ->
        print("$element,")
    }
    println()

    // it으로 람다를 대신하여 객체를 받아올 수 있다.
    array.forEach {
        print("$it,")
    } // => 1,2,3,4,5
}

Output:

1,2,3,4,5,
1,2,3,4,5,
1,2,3,4,5,

filter 함수

filter 함수는 목록에 조건을 걸어 그 조건에 맞는 새로운 목록을 반환한다.

fun main() {
    val array = arrayOf(1, 2, 3, 4, 5) // => 1,2,3,4,5 배열을 생성한다.

    // filter의 조건에 충족되는 함수를 반환한다.
    array.filter({ e -> e % 2 == 0 }).forEach { println(it) } // => 2,4

    // 괄호'()'은 생략할 수 있다.
    array.filter { e -> e % 2 == 0 }.forEach { println(it) } // => 2,4

    // lambda 사용하지 않고도 'it'으로 객체를 받아 올 수 이 있다.
    array.filter { it % 2 == 0 }.forEach { println(it) } // => 2,4

}

Output:

2,4,
2,4,
2,4,

map 함수

map 함수는 목록의 요소를 변경하여 받아올 수 있다.

// 이름과 연령을 갖는 클래스 정의
private class Person(val name: String, val age: Int)

fun main() {
    val array = arrayOf(
        Person("Charlie", 20),
        Person("devkuma", 31),
        Person("kimkc", 42),
    )

    // lambda으로 user 인스턴스를 받아 올수 있다.
    array.map({ user -> user.name }).forEach { print("${it},") }
    println()

    // 괄호'()'은 생략할 수 있다.
    array.map { user -> user.name }.forEach { print("${it},") }
    println()

    // 'it'으로 객체를 받아 올 수 있다(이 'it'는 user 인스턴스를 가르킨다).
    array.map { it.name }.forEach { print("${it},") }
}

Output:

Charlie,devkuma,kimkc,
Charlie,devkuma,kimkc,
Charlie,devkuma,kimkc,

sum 함수

sum 함수는 입력한 숫자를 합산한다.

fun main() {
    // Array<Int> 인스턴스 생성한다.
    val array = arrayOf(1, 2, 3, 4, 5)

    // 합산한다(1 + 2 + 3 + 4 + 5).
    println(array.sum()) // => 15
}

Output:

15

take 함수

take 함수는 목록의 요소를 입력한 숫자 만큼만 가져온다.

fun main() {
    val array = arrayOf(1, 2, 3, 4, 5)
    array.take(1).forEach { print(it) } // => 1
    println()
    array.take(2).forEach { print(it) } // => 1, 2
    println()
    array.take(3).forEach { print(it) } // => 1, 2, 3
    println()
    array.take(4).forEach { print(it) } // => 1, 2, 3, 4
    println()
    array.take(5).forEach { print(it) } // => 1, 2, 3, 4, 5
}

Output:

1
12
123
1234
12345

drop 함수

drop 함수는 목록의 요소를 앞에서 부터 입력한 숫자 만큼 제거하고 가져온다.

fun main() {
    val array = arrayOf(1, 2, 3, 4, 5)
    array.drop(1).forEach{print(it)} // => 2, 3, 4, 5
    println()
    array.drop(2).forEach{print(it)} // => 3, 4, 5
    println()
    array.drop(3).forEach{print(it)} // => 4, 5
    println()
    array.drop(4).forEach{print(it)} // => 5
    println()
    array.drop(5).forEach{print(it)} // => 빈 Array
}

Output:

2345
345
45
5

참조