람다식을 Kotlin에서도 사용할 수 있다.
가장 많이 사용하는 람다로 map이 있다. mapping의 약자인 듯 보인다. 기존 값을 사용하여 새로운 값을 맵핑해 준다는 의미로 보이는데 아래와 같이 사용한다.
fun map() {
val list = listOf(1, 2, 3, 4)
val result = list.map { n:Int -> "[$n]" }
val result2 = list.map { n -> "[$n]" }
val result3 = list.map { "[${it}]" }
println(result)
println(result2)
println(result3)
val listChar = listOf('a', 'b', 'c', 'd')
val resultChar = listChar.map { "[${it.toUpperCase()}]" }
println(resultChar)
}
위의 3가지 경우(result ~ result3) 모두 같은 값을 출력한다.
동일한 list를 동일한 형식으로 바꾸는 다른 방법임을 알 수 있다. 람다 식 안에서 받아지는 변수명은 자동으로 it 이 된다.
문자에서도 비슷한 방식으로 사용할 수 있음을 4번째 예에서 볼 수 있다.
람다 중에 List를 하나의 문자로 합쳐주는 joinToString 도 있다. 사용법은 아래와 같다.
fun joinToString() {
val list = listOf(1, 2, 3, 4)
val resultJoinToString = list.joinToString(" ") { "[$it]" }
val resultJoinToString2 = list.joinToString(separator = " ", transform = { "[$it]"})
println(resultJoinToString)
println(resultJoinToString2)
}
1 ~ 4까지의 숫자를 문자형태로 바꾸어서 합쳐주는 것인데, joinToString이 여러개의 파라미터를 받고 있으므로 () 뒤에 람다를 써서 사용할 수 있다.
같은 효과지만 명시적으로 transform 이라는 파라미터 이름에 람다를 정의할 수도 있다.
map과 비슷하지만 mapIndexed라는 람다도 사용해 볼 수 있다.
mapIndexed는 index(순서)를 같이 반환해 준다.
fun mapIndexed() {
val list = listOf('a', 'b', 'c')
val result = list.mapIndexed { index, element -> "[$index: $element]" }
val result2 = list.mapIndexed { index, _ -> "[$index]" }
val result3 = list.mapIndexed { _, element -> "[$element]" }
println(result)
println(result2)
println(result3)
}
mapIndexed는 index와 원소를 인자로 받는다. 두 가지 중 한 개의 값을 받지 않고 싶을 때는 "_"를 사용하면 된다.
람다를 사용하는 이유 중 하나는 가독성이 높은 코드를 만들 수 있기 때문이다. 다음의 예를 통해 알 수 있다.
2보다 큰 숫자만 골라내는 전통적인 방법이다.
fun iterateFilter() {
val list = listOf(1, 2, 3, 4)
val result = mutableListOf<Int>()
for (i in list) {
if (i > 2) {
result += i
}
}
println(result)
}
간단한 코드이기 때문에 금방 알 수있지만 이러한 for 문들이 코드 곳곳에 녹아 있다면 코드를 읽어 내려가기가 쉽지 않다. 람다를 쓸 경우에는 아래와 같이 간단하게 사용 가능하다.
fun filter() {
val list = listOf(1, 2, 3, 4)
val even = list.filter { it % 2 == 0 }
val greaterThan2 = list.filter { it > 2 }
println(even)
println(greaterThan2)
}
단순이 filter라는 람다에 조건을 서술한 술어(boolean을 반환하는 predicate)을 작성하면 된다. filter 함수의 결과는 아래와 같다.
람다는 변수에 담아 재사용할 수 있다.
fun filter() {
val list = listOf(1, 2, 3, 4)
val isEven = { e:Int -> e % 2 == 0}
val result = list.filter(isEven)
val result2 = list.any(isEven)
println(result)
println(result2)
}
위의 코드에서는 isEven 이라는 람다를 정의해 두고 두 곳에서 재활용 했다. 결과는 아래와 같다.
람다 밖의 요소를 참조할 수 있는 것을 클로져라 한다. 다음과 같은 경우를 참고할 수 있다.
fun foreachClosure() {
val list = listOf(1, 5, 7, 10)
var sum = 0
val divider = 5
list.filter { it % divider == 0 }
.forEach { sum += it }
println(sum)
val resultSum = list.filter { it % divider == 0 }.sum()
println(resultSum)
}
divider 또는 sum과 같은 변수를 람다 안에서 사용하게 되는 경우 이를 클로져라 한다.
위와 같이 foreach를 사용하게 될 경우, 컬랙션의 매 원소의 값에 람다를 적용할 수 있다. 단순히 값을 sum 하는 경우라면 foreach를 사용하는 대신에 바로 sum 함수를 사용할 수 있다.
'Develop! > Kotlin' 카테고리의 다른 글
멤버참조 in Kotlin (0) | 2023.09.27 |
---|---|
컬렉션에 대한 연산 in Kotlin (0) | 2023.09.25 |
제네릭스 in Kotlin (0) | 2023.09.22 |
안전한 호출과 엘비스 연산자 in kotlin (0) | 2023.09.14 |
Null이 될 수 없는 타입 in Kotlin (0) | 2023.09.06 |