일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Design Pattern
- Functional Programming
- 팩토리 메소드
- ㅓ
- F
- Singleton
- r
- 빌터패턴
- 추상팩토리패턴
- 코틀린
- 디자인패턴
- 싱글톤
- ㅋㅁ
- a
- PrototypePattern
- 추상 팩토리
- 디자인패턴 #
- Abstract Factory
- designPattern
- El
- builderPattern
- 함수형프로그래밍
- 옵저버 패턴
- Kotlin
- Observer Pattern
- factory method
- 프로토타입 패턴
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
람다로 프로그래밍(컬렉션 함수형 API) 본문
- 함수형 프로그래밍 스타일을 사용하면 컬렉션을 다룰 때 매우 편리하다
- 많은 작업에 라이브러리 함수를 활용하고 코드가 간결해진다.
필수적인 함수: filter와 map
컬렉션을 활용할 때 기반이 되는 함수이며 대부분의 컬렉션 연산을 이 두 함수를 통해 표현 가능하다
filter 함수
- 컬렉션은 이터레이션 하면서 주어진 람다에 각 원소를 넘겨서 람다가 true를 반환하는 원소만 모은다.
- predicate를 만족하는 새로운 컬렉션을 반환한다.
- 원치 않는 원소를 제거한다 하지만 filter는 원소를 변환할 수는 없다
- 원소를 변환하려면 map함수를 사용한다.
fun main() {
val people = listOf(Person("kim",15), Person("hong", 18),
Person("park",12),Person("Bob", 31), Person("Alice",9))
println(people.filter { it.age >= 15 })
}
map 함수
- 주어진 람다를 컬렉션의 각 원소에 적용한 결과를 모아서 새로운 컬렉션을 만든다.
fun main() {
val people = listOf(Person("kim",15), Person("hong", 18),
Person("park",12),Person("Bob", 31), Person("Alice",9))
println(people.map {it.name})
}
*두 함수를 쉽게 연쇄시킬 수 있다.
15세 이상의 사람의 이름 출력하기
fun main() {
val people = listOf(Person("kim",15), Person("hong", 18),
Person("park",12),Person("Bob", 31), Person("Alice",9))
println(people.filter { it.age >= 15 }.map { it.name})
}
최고 연장자 구하기
fun main() {
val people = listOf(Person("kim",15), Person("hong", 18),
Person("park",12),Person("Bob", 31), Person("Alice",9))
//println(people.filter { it.age == people.maxBy(Person::age)!!.age})
// maxBy 함수가 사람이 100명이라면 100번 호출됨
val maxAge = people.maxBy { it.age }!!.age
println(people.filter { it.age == maxAge })
}
주석을 처리한 부분처럼 람다 안에 람다식을 넣을 경우 100명의 사람이 있다면 연산이 100번된다. 매우 불합리하다.
map 컬렉션의 경우 키와 값을 처리하는 함수가 따로 존재한다.
filterKeys MapKeys filterValues mapValues
fun main() {
val numberMap = mapOf(0 to "zero", 1 to "one", 2 to "two", 3 to "three", 4 to "four")
println(numberMap.filterKeys { it > 3 })
println(numberMap.mapKeys { it.key * 2 })
println(numberMap.filterValues { it == "two" })
println(numberMap.mapValues { it.value.toUpperCase() })
}
all, any, count, find 컬렉션 predicate 적용하기
fun main() {
val people = listOf( Person("Alice", 27), Person("Bob", 31), Person("kim", 19),
Person("hong", 25), Person("park", 12))
val canBeInClub25 = {p:Person -> p.age >= 25}
println(people.all(canBeInClub25)) // 모든사람이 25살 이상을 만족하는지 확인.
println(people.any(canBeInClub25)) // 25살 이상의 사람이 존재하는지
println(people.count(canBeInClub25)) // 몇명이나 25살 이상인지 확인한다.
println(people.find(canBeInClub25)) // 가장 조건을 먼저 만족한다고 확인된 원소를 가져온다. 없으면 null을 반환한다.
}
* people.filter(canBeInClub25). size, 25살 이상의 사람을 모은 중간 컬렉션이 생기지만
count를 사용하면 그 숫자만 추적하기 때문에 count가 훨씬 효과적이다.
groupBy : 리스트를 여러 그룹으로 이루어진 맵으로 변경
어떤 특성에 따라 여러 그룹으로 나누고 싶을 때 사용한다.
아래의 예 같은 경우는 Map <Int, List <Person>>을 반환한다.
fun main() {
val list = listOf("a", "ab", "abc", "bcd","bbb")
println(list.groupBy { it.first() })
}
flatMap과 flatten: 중첩된 컬렉션 안의 원소 처리 하기
flatMap
- 인자로 주어진 람다를 컬렉션의 모든 객체에 적용한다.(맵핑)
- 람다를 적용한 결과 얻어진 리스트를 한 개의 리스트로 모아준다.(펼치기)
fun main() {
val strList = listOf("abcd", "defgh")
println(strList.flatMap { it.toList() })
}
1. "abcd" -> [a, b, c, d] "defgh" -> [d, e, f, g, h]
2. [ [a, b, c, d] , [d, e, f, g, h] ] ---> [a, b, c, d, d, e, f, g, h]
data class Book(val title: String, val authors: List<String>)
fun main() {
val books = listOf(
Book("Thursday Next", listOf("jasper Fforde")),
Book("Mort", listOf("Terry Pratchett")),
Book("Good Omens", listOf("Terry Pratchett", "Neil Gaiman")))
println(books.flatMap { it.authors })
println(books.flatMap { it.authors }.toSet())
}
1 인자로 주어진 람다 적용.
Book("Thursday Next", listOf("jasper Fforde")) ----> listOf("jasper Fforde")
Book("Mort", listOf("Terry Pratchett")) ----> listOf("Terry Pratchett")
Book("Good Omens", listOf("Terry Pratchett", "Neil Gaiman")) ----> listOf("Terry Pratchett", "Neil Gaiman")
2 결과 얻어진 리스트를 한 개의 리스트로 모아준다
[jasper Fforde, Terry Pratchett, Terry Pratchett, Neil Gaiman]
3 집합 연산 적용
[jasper Fforde, Terry Pratchett, Neil Gaiman]
* 리스트에 리스트가 있는데 중첩된 리스트의 원소를 한 리스트로 모아야 할 경우 flatMap이 효과적이다.
list 안에 list가 있는데 각 원소를 한 리스트로 모으고 싶다면 flatMap, flatten을 사용해라.
특별히 변환할 필요가 없다면 flatten을 통해 리스트를 평평하게 펼치기만 한다.
fun main() {
val listOfList = listOf( listOf("a","b","c"), listOf("c","d","e"), listOf("f","g","h") )
println(listOfList.flatten())
}
** 컬렉션을 다루는 코드를 작성할 경우 원하는 바를 어떻게 일반적인 변환을 통해 표현할지 생각해보고
그 변환에 맞는 라이브러리 함수가 있는지 찾아봐라 대부분 구현되어있다.
그러면 직접 구현하는 것보다 훨씬 빠르고 효과적으로 문제를 해결할 수 있다.
'Kotlin in Action > 코틀린 기초' 카테고리의 다른 글
람다로 프로그래밍 (자바 함수형 인터페이스 사용) (0) | 2020.08.18 |
---|---|
람다로 프로그래밍 (지연계산(Lazy) 컬렉션 연산) (0) | 2020.08.16 |
람다로 프로그래밍 (0) | 2020.08.16 |
클래스 객체 인터페이스(Object 키워드 : 클래스 선언과 인스턴스 생성) (0) | 2020.08.14 |
클래스 객체 인터페이스(컴파일러가 생성한 메소드: 데이터 클래스와 클래스 위임) (0) | 2020.08.14 |