Kotlin

[Kotlin] 컬렉션 처리 API 확장 & 가변 인자(vararg) 함수

sh1mj1 2024. 1. 3. 15:23

Kotlin in Action 을 공부하고 Effective kotlin 의 내용을 조금 참조하여 정리한 글입니다.

 

이미지 출처   https://commons.wikimedia.org/wiki/File:Kotlin_Icon.svg

자바 컬렉션 API 확장

이전에 코틀린 컬렉션은 자바와 같은 클래스를 사용하지만 더 확장된 API 를 제공한다고 했다. 

@Test
fun collectionExtension() {
    val strings: List<String> = listOf("first", "second", "fourteenth")
    println(strings.last()) // fourteenth printed

    val numbers: Collection<Int> = setOf(1, 14, 2)
    println(numbers.max()) // 14 printed
}

이런 코드가 어떻게 작동할까? 어떻게 자바 라이브러리의 컬렉션에 대해 코틀린에서 새로운 기능을 추가할 수 있을까?

`last` 와 `max` 는 확장함수였던 것이다!!!!

 

`last` 의 구현은 대략 아래처럼 되어 있다.

public fun <T> List<T>.last(): T {
    if (isEmpty())
        throw NoSuchElementException("List is empty.")
    return this[lastIndex]
}

 

`max` 의 구현은 대략 아래처럼 되어 있다.

public fun <T : Comparable<T>> Iterable<T>.max(): T? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    var max = iterator.next()
    while (iterator.hasNext()) {
        val e = iterator.next()
        if (max < e) max = e
    }
    return max
}

 

이 밖에 코틀린 표준 라이브러리는 수많은 확장 함수를 포함한다.

이러한 것들을 모두 다 알 필요는 없고 어떤 객체에 사용할 수 있는 메서드나 함수가 궁금할 때마다 IDE 의 코드 완성 기능을 통해 살펴보고, 원하는 함수를 선택하면 된다.

코틀린 표준 라이브러리 참조 매뉴얼을 보면 각 라이브러리 클래스가 제공하는 모든 메서드(멤버 메서드와 확장 함수)를 볼 수 있다.

인자의 개수가 달라질 수 있는 가변 인자 함수

이전에도 계속 사용했듯이 리스트를 생성하는 함수를 호출할 때 원하는 만큼 원소를 전달할 수 있다.

val list = listOf(2, 3, 5, 7, 11)

이 함수의 정의는 아래처럼 되어 있다.

fun <T> listOf(vararg elements: T): List<T> {
    return if (elements.size > 0) elements.asList() else emptyList()
}

 

자바의 가변 인자(`varargs`)는 메서드를 호출할 때 원하는 개수만큼 값을 인자로 넘기면 자바 컴파일러가 배열에 그 값들을 넣어준다. 

코틀린의 가변인자도 자바와 비슷하다. 

public void printNumbers(int... numbers) {
    for (int number : numbers) {
        System.out.print(number + " ");
    }
}

int[] numbers = {1, 2, 3, 4, 5};
printNumbers(numbers); // 배열을 직접 전달
fun printNumbers(vararg numbers: Int) {
    numbers.forEach { number ->
        print("$number ")
    }
}

val numbers = intArrayOf(1, 2, 3, 4, 5)
printNumbers(*numbers) // 스프레드 연산자를 사용하여 배열을 가변 인자로 전달

자바에서는 타입 뒤에 `...` 을 붙인다.

코틀린에서는 그 대신 파라미터 앞에 `vararg` 변경자를 붙인다.

 

이미 배열에 들어있는 원소를 가변 길이 인자로 넘길 때도 코틀린과 자바 구문이 다르다.

자바에서는 배열을 그냥 넘기면 된다.

코틀린에서는 배열을 명시적으로 풀어서 배열의 각 원소가 인자로 전달되게 해야 한다.

코틀린 spread(스프레드) 연산자가 그런 작업을 해준다. 전달하려는 배열 앞에 `*` 를 붙여주면 된다.

@Test
fun varargTest() {
    val numbers = intArrayOf(1, 2, 3)
    printNumbers(*numbers) // 스프레드 연산자를 사용하여 배열을 가변 인자로 전달
    printNumbers(*numbers, 4, 5) // 배열의 요소와 추가적인 값들을 함께 전달
}
출력 결과
1 2 3
1 2 3 4 5 

위처럼 스프레드 연산자 `*` 를 통하면 배열에 들어있는 값과 다른 추가적인 값들을 함께 써서 함수를 호출할 수 있다.

이런 기능은 자바에서는 사용할 수 없다.

 

 

 

참조 : 

https://black-jin0427.tistory.com/214