본문 바로가기

카테고리 없음

Sequence

kotlin standard library는 Collection과 함께 Sequences(Sequence<T>)를 포함하고 있습니다. 컬렉션과 달리 시퀸스는 엘리먼트를 포함하지 않으며 반복하는 동안 엘리먼트를 생성합니다. 시퀸스는 Iterable과 동일한 기능을 제공하지만 여러 단계 처리에 대한 다른 접근방식을 구현 합니다.

 

 

Iterable 

  • 여러 과정을 처리할 때 각 단계를 완료하고 그 결과인 중간 컬렉션을 반환합니다.
  • 전체 컬렉션의 각 단계를 완료하고 그 다음단계로 진행

시퀸스 

  • 여러단계의 처리는 바로 실행하지 않고 전체 단계가 처리된 결과가 요청되었을 때 실제 시퀸스 연산이 일어나면서 lazily하게 처리 됩니다.
  • 모든 단일 요소에 대해 처리를 one-bt-one 형태로 수행합니다.
  • 중간 처리 단계를 피해 전체 컬렉션의 체이닝 동작에서 퍼포먼스 향상하지만 이러한 lazy의 특성은 간단한 계산이나 작은 컬렉션 처리시 불필요한 오버헤드가 발생할 수 있습니다.

 

From elements

시퀀스를 만들기 위해서는 sequenceOf() 함수를 호출하고 인자들을 나열하면 됩니다.

val numbersSequence = sequenceOf("four", "three", "two", "one")

From an Iterable

Iterable객체(List와 Set등)를 asSequence()를 호출해서 시퀀스로 만들 수 있습니다.

val numbers = listOf("one", "two", "three", "four")
val numbersSequence = numbers.asSequence()

From a Function

시퀀스의 요소들을 계산 할 수 있는 방식인 generateSequence()함수와 함께 구축하는 방법도 있습니다. 선택적으로 첫번째 인자를 명시적으로 선언할 수 있습니다. 이런 시퀀스 생성은 null을 반환하면 중지됩니다. 아래 예제를 보면 무한한 시퀀스가 있습니다.

val oddNumbers = generateSequence(1) { it + 2 } // `it` is the previous element
//println(oddNumbers.take(5).toList()) // Result : [1, 3, 5, 7, 9]

println(oddNumbers.count())     // error: the sequence is infinite
// Result : Evaluation stopped while it's taking too long️

generateSequence()를 사용할 때 유한한 시퀀스를 만들기 위해서는 마지막 요소 다음에 null을 반환해야 합니다.

val oddNumbersLessThan10 = generateSequence(1) { if (it < 8) it + 2 else null }
println(oddNumbersLessThan10.count()) // Result: 5

From chunk

마지막으로 시퀀스를 임의의 크기의 덩어리로 생성할 수 있는 기능이 있습니다. 이 기능은 람다 함수내에서 호출할 수 있는 yield() 그리고 yieldAll() 함수입니다. 이 함수는 시퀀스 소비자에게 요소들을 반환하고 소비자가 다음 요소를 요청할 때 까지 sequence() 실행을 일시중단 합니다. yield()는 단일 요소를 인자로 가지고 yieldAll()은 Iterable객체를 인자로 가지고 Iterator나 다른 Sequence도 가질 수 있습니다. yieldAll에 인자로 들어가는 Sequence는 무한할 수 있지만 모든 후속 호출은 실행되지 않기 때문에 마지막에만 호출해야 합니다.

val oddNumbers = sequence {
    yield(1)
    yieldAll(listOf(3, 5))
    yieldAll(generateSequence(7) { it + 2 })
}
println(oddNumbers.take(5).toList())
728x90