람다 함수형 프로그래밍은 컬렉션을 사용할 때 간결하게 작성할 수 있어서 매우 편리하다
컬렉션을 iteration 하면서 주어진 람다에 각 원소를 넘겨 람다가 조건에 맞는, true를 반환하는 원소만 필터링한다
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> println(people.filter { it.age > 30 })
[Person(name = Bob, age = 31)]
filter 함수는 컬렉션에서 원치 않는 원소들을 제거한다. 하지만 원소를 변환할 수는 없다. 원소를 변환하기 위해서는 map 메서드를 사용해야 한다.
각 원소를 원하는 형태로 변환하는 기능을 하며, 변환한 결과를 모아 새 컬렉션을 만든다
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> println(people.map { it.name })
[Alice, Bob]
람다의 멤버 참조를 사용하면 다음과 같이 작성할 수 있다.
people.map(Person::name)
멤버 참조?
::를 사용하는 방식으로, 프로퍼티나 메소드를 단 하나만 호출하는 함수 값을 만들어준다data class Person( val name: String, val age: Int ) -> Person::name // Person의 name 프로퍼티를 객체로 반환
컬렉션의 모든 원소가 조건을 만족하는지 판단한다. 반환 타입은 Boolean이다.
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> val canBeInClub30 = { p: Person -> p.age <= 30)
>>> println(people.all(canBeInClub30))
false
컬렉션의 원소 중에, 조건을 만족하는 원소가 하나라도 있는지 판단한다. 반환타입은 Boolean이다.
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> val canBeInClub30 = { p: Person -> p.age <= 30)
>>> println(people.any(canBeInClub30))
true
Tip) !all과 !any를 사용할 수는 있지만, ! 연산자를 눈치 채지 못하는 경우가 있기 때문에 가독성을 높이기 위해 가급적이면 any와 all 앞에 !를 붙이지 않는 편이 낫다
조건을 만족하는 원소의 개수 반환한다. 반환 타입은 Int이다.
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> val canBeInClub30 = { p: Person -> p.age <= 30)
>>> println(people.count(canBeInClub30))
1
Tip) count와 size
>> println(people.filter(canBeInClub30).size) 1
count가 아닌 size를 활용하여 처리하면 조건을 만족하는 모든 원소가 들어가는 중간 Collection이 생긴다.
count는 조건을 만족하는 원소의 개수만 추적하지 조건을 만족하는 원소를 따로 저장하지 않기 때문에 count가 훨씬 효율적이다.
조건을 만족하는 첫번째 원소 반환하고, 만족하는 원소가 없다면 null을 반환한다
>>> val strings = listOf("abc", "def")
>>> println(strings.flatMap { it.toList() })
[a, b, c, d, e, f]
firstOrNull과 기능이 동일하다
그렇기에 조건을 만족하는 원소가 없으면 null이 반환된다는 사실을 명확하게 표현하고 싶다면 firstOrNull을 사용해도 무방하다
리스트를 어떠한 특성에 따라 여러 그룹으로 이루어진 Map으로 변경한다
>>> val people = listOf(Person("A", 24), Person("B", 31), Person("C", 24))
>>> println(people.groupBy {it.age})
{ 24=[Person(name=A, age=24), Person(name=C, age=24)], 31=[Person(name=B, age=31)] }
중첩된 컬렉션 안의 원소 처리한다
flatMap은 주어진 람다를 컬렉션의 모든 객체에 적용하고, 적용한 결과로 얻어지는 여러 리스트를 한 리스트로 flat하게 만드는 함수이다
>>> val strings = listOf("abc", "def")
>>> println(strings.flatMap { it.toList() })
[a, b, c, d, e, f]
리스트 원소를 사용해서 특별히 변환해야 할 내용이 없다면, 단순히 펼치기만 하는 flatten 함수를 사용할 수 있다.