이번에는 Kotlin의 Collection과 Sequence에서 사용할 수 있는 filter, map 함수의 호출 순서에 따른 성능 차이에 대해 간단하게 다뤄보려고 한다.
map, filter vs filter, map
1 2 3 4
| data class Person( val name: String, val age: Int )
|
- 사용될 list는 동일하다.
- 먼저, map() 함수를 수행한 뒤, filter() 함수를 수행한다.
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 29 30 31 32 33 34 35
| fun testMapAndFilter() { val list = listOf( Person("Alice", 27), Person("hzoou", 25), Person("txxbro", 28), Person("iyj", 28), Person("WooVictory", 27))
val result = list.map(::mapToName) .filter(::filterByAge) println(result) }
fun mapToName(person: Person): Int { println("map : ${person.name}") return person.age }
fun filterByAge(age: Int): Boolean { println("filter : $age") return age > 27 }
map : Alice map : hzoou map : txxbro map : iyj map : WooVictory filter : 27 filter : 25 filter : 28 filter : 28 filter : 27 [28, 28]
|
- map()으로 인해 5번, filter()로 인해 5번 => 총 10회
- 다음으로는 filter() 함수를 수행한 뒤, map() 함수를 수행한다.
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 29 30 31 32 33
| fun testFilterAndMap() { val list = listOf( Person("Alice", 27), Person("hzoou", 25), Person("txxbro", 28), Person("iyj", 28), Person("WooVictory", 27))
val result = list.filter { filterByAge(it.age) } .map(::mapToName)
println(result) }
fun mapToName(person: Person): Int { println("map : ${person.name}") return person.age }
fun filterByAge(age: Int): Boolean { println("filter : $age") return age > 27 }
filter : 27 filter : 25 filter : 28 filter : 28 filter : 27 map : txxbro map : iyj [28, 28]
|
- filter()로 인해 5번, filter()의 결과를 map()한 결과로 인해 2번 => 총 7회
연산의 순서를 변경함으로써 수행되는 연산의 횟수를 줄여 성능을 개선할 수도 있다. 연산의 순서를 항상 바꿀 수 있는 것은 아니지만, 위의 경우처럼 변경이 가능한 경우에는 원소를 줄여주는 연산을 먼저 수행하면 전체 연산의 수를 줄일 수 있다.
이는 collection, sequence 모두 해당된다.
하지만, 이 경우에는 collection 연산은 여전히 intermediate collection을 생성한다는 문제가 존재한다.
Reference