컬렉션을 처리할 때 쓸 수 있는 코틀린 표준 라이브러리 함수
- vararg 키워드를 사용하면 호출 시 인자 개수가 달라질 수 있는 함수를 정의할 수 있다.
- 중위(infix)함수 호출 구문을 사용하면 인자가 하나뿐인 메소드를 간편하게 호출할 수 있다.
- 구조 분해 선언(destructuring declaration)을 사용하면 복합적인 값을 분해해서 여러 변수에 나눠 담을 수 있다.
1. 자바 컬렉션 API 확장
코틀린 컬렉션은 자바의 클래스보다 더 확장된 API를 제공한다.
>>> val strings:List<String> = listOf("first", "second", "fourteenth")
>>> strings.last()
fourteenth
>>> val numbers:Collection<Int> = setOf(1, 14, 2)
>>> numbers.max()
14
자바 라이브러리 클래스의 인스턴스인 컬렉션에 대해 코틀린이 새로운 기능을 추가할 수 있을까?
⇒ last와 max는 모두 확장 함수였던 것!
fun <T> List<T>.last(): T { /* 마지막 원소를 반환함 */ }
fun Collection<Int>.max(): Int { /* 컬렉션의 최댓값을 찾음 */ }
2. 가변 인자 함수: 인자의 개수가 달라질 수 있는 함수 정의
리스트를 새성하는 함수를 호출할 때 원하는 만큼 많이 원소를 전달할 수 있다.
var list = listOf(2, 3, 5, 7, 11)
라이브러리에서 이 함수의 정의를 보면 다음과 같다.
fun listOf<T>(varargs values: T): List<T> { ... }
코틀린의 가변 길이 인자도 자바의 가변 길이 인자와 비슷하다. 다만 문법이 조금 다르다. 타입 뒤에 ...를 붙이는 대신 코틀린에서는 파라미터 앞에 vararg 변경자를 붙인다.
자바로 표현해보자면 아래정도가 될 거 같다.
public static <T> List<T> listOf(T... args){
return Arrays.asList(args);
}
이미 배열에 들어있는 원소를 가변 길이 인자로 넘길 때도 코틀린과 자바 구문이 다르다. 자바에서는 배열을 그냥 넘기면 되지만 코틀린에서는 배열을 명시적으로 풀어서 배열의 각 원소가 인자로 전달되게 해야 한다. 기술적으로는 스페드(spread) 연산자가 그런 작업을 해준다. 하지만 실제로 전달하려는 배열 앞에 *를 붙이기만 하면 된다.
fun main(args: Array<String>){
val list = listOf("args: ", *args) // 스프레드 연산자가 배열의 내용을 펼쳐준다.
println(list)
}
이 예제는 스프레드 연산자를 통하면 배열에 들어있는 값과 다른 여러 값을 함께 써서 함수를 호출할 수 있음을 보여준다. 이런 기능은 자바에서는 사용할 수 없다.
3. 값의 쌍 다루기: 중위 호출과 구조 분해 선언
val map = mapOf(1 to "one", 7 to "seven", 53 to "fifty-three")
여기서 to 라는 단어는 코틀린 키워드가 아니다. 이 코드는 중위 호출(infix call) 이라는 특별한 방식으로 to라는 일반 메소드를 호출한 것이다.
중위 호출 시에는 수신 객체와 유일한 메소드 인자 사이에 메소드 이름을 넣는다. (이때 객체, 메소드 이름, 유일한 인자 사이에는 공백이 들어가야 한다.) 다음 두 호출은 동일하다.
1.to("one") // to 메소드를 일반적인 방식으로 호출
1 to "one" // to 메소드를 중위 호출 방식으로 호출
인자가 하나뿐인 일반 메소드나 인자가 하나뿐인 확장 함수에 중위 호출을 사용할 수 있다. 함수(메소드)를 중위 호출에 사용하게 허용하고 싶으면 infix 변경자를 함수 선언 앞에 추가해야 한다.
to 함수의 정의를 간략하게 줄인 코드
infix fun Any.to(other:Any) = Pair(this, other)
이 to 함수는 Pair의 인스턴스를 반환한다. Pair는 코틀린 표준 라이브러리 클래스로, 그 이름대로 두 원소로 이뤄진 순서쌍을 표현한다.
Pair의 내용로 두 변수를 즉시 초기화할 수 있다.
val (number, name) = 1 to "one"
이런 기능을 구조 분해 선언(destructuring declaration) 이라고 부른다.
Pair 인스턴스 외 다른 객체에도 구조 분해를 적용할 수 있다. 예를 들어 key와 value라는 두 변수를 맵의 원소를 사용해 초기화할 수 있다.
루프에서도 구조 분해 선언을 활용할 수 있는데 joinToString에서 본 wihIndex를 구조 분해 선언과 조합하면 컬렉션 원소의 인덱스와 값을 따로 변수에 담을 수 있다.
for((index, element) in collection.withIndex()){
println("$index: $element")
}
mapOf 함수의 선언
fun <K,V> mapOf(vararg values: Pair<K, V>): Map<K, V>
'프로그래밍 노트 > Kotlin' 카테고리의 다른 글
[Kotlin] 코틀린 로컬함수와 확장 (0) | 2020.11.24 |
---|---|
[Kotlin] 코틀린 문자열과 정규식 다루기 (0) | 2020.11.24 |
[Kotlin] 코틀린(Kotlin) 메소드를 다른 클래스에 추가(확장 함수와 확장 프로퍼티) (0) | 2020.11.19 |
[Kotlin] 코틀린(Kotlin) 함수만들기 (0) | 2020.11.14 |
[Kotlin] 코틀린(Kotlin)에서 컬렉션 만들기 (0) | 2020.11.14 |