Sequences

최희창·2022년 12월 18일
0

Kotlin

목록 보기
13/13

1. Collections vs Sequences

  • Collections에 대해 정의된 lambda를 인자로 받는 확장함수들은 inline function으로 익명 클래스 객체 생성을 하지 않아 퍼포먼스 오버헤드 걱정없이 자유롭게 사용할 수 있다.
  • 그러나 Collections의 확장함수들은 호출될 때 마다 새로운 Collection이 생성되어 반환되어 지고 있다.
val list = listOf(1, 2, -3)   // [1, 2, -3] 생성
val maxOddSquare = list
    .map { it * it }          // [1, 4, 9] 생성
    .filter { it % 2 == 1 }   // [1, 9] 생성
    .max()

-> 총 3개의 intermediate collection이 생성되는 비효율성이 존재한다.

  • 대개 Collection을 다룰 때 다양한 확장함수를 이용해 chain calls 패턴을 많이 이용하므로 해당 문제를 피하기 위한 방법으로 sequence가 소개되고 있다.
  • Kotlin의 sequence는 Java8의 stream에 대응되는 개념으로 lazy evaluation 방식으로 처리한다. Collection은 연산에 대해 eager evaluation으로 처리하지만, sequence는 연산에 대해 lazy evaluation으로 처리한다.
val list = listOf(1, 2, -3)   // [1, 2, -3] 생성
val maxOddSquare = list
    .asSequence()
    .map { it * it }
    .filter { it % 2 == 1 }
    .max()

-> 결과가 필요한 시점에만 연산을 수행(lazy evaluation)하여 최종 결과만을 반환한다.

More

fun m(i: Int): Int {
    print("m$i ")
    return i
}
fun f(i: Int): Boolean {
    print("f$i ")
    return i % 2 == 0
}
val list = listOf(1, 2, 3, 4)
// 1. Collection (m1 m2 m3 m4 f1 f2 f3 f4)
list.map(::m).filter(::f)
// 2. Sequence (m1 f1 m2 f2 m3 f3 m4 f4)
list.asSequence().map(::m).filter(::f).toList()
// 3. Sequence - terminal operation이 없는 경우 (nothing is printed)
list.asSequence().map(::m).filter(::f)

-> collection의 경우 n개의 원소 전부에 대해 map() transform을 한 뒤에 find()로 조건에 맞는 첫번째 원소를 찾는다. sequence의 경우 앞 인덱스부터 하나씩 transform을 하고 find()로 조건이 맞는지 확인하며 조건이 맞는 원소가 발견되면 연산을 종료한다.

profile
heec.choi

0개의 댓글