카샤의 만개시기

Kotlin Sequence(시퀀스) 본문

Kotlin

Kotlin Sequence(시퀀스)

SKaSha 2019. 12. 8. 06:51

시퀀스는 순차적인 컬렉션으로 요소의 크기를 특정하지 않고, 나중에 결정할 수 있는 컬렉션이다.
예를 들어 특정 파일을 줄 단위로 읽어서 마지막 라인 수를 모를때 사용할 수 있다.
따라서 시퀀스는 처리 중에는 계산하고 있지 않다가 toList()count()와 같은 최종 연산에 의해 결정 된다.

generateSequence()로 생성

fun main() {
    // 시드값 1을 시작으로 1씩 증가하는 시퀀스 정의
    val nums: Sequence<Int> = generateSequence(1) { it + 1 }

    // take()를 사용해 원하는 요소 개수만큼 획득하고 toList()를 사용해 List 컬렉션으로 반환
    println(nums.take(10).toList())
}

위 코드에서 take(10)을 했을때까지는 시퀀스를 어떻게 처리할지 정의만 한것이고,
실제 실행은 toList()를 호출했을때 이루어진다.

asSequence()

fun main() {
    // 단순 메서드 체이닝을 사용할 때
    val list1 = listOf(1, 2, 3, 4, 5)
    val listDefault = list1
            .map { println("map($it) "); it * it } 
            .filter { println("filter($it) "); it % 2 == 0 } 

    // asSequence()의 사용
    val listSeq = list1.asSequence()
            .map { print("map($it) "); it * it } 
            .filter { println("filter($it) "); it % 2 == 0 }
            .toList()
}

단순 메서드 체이닝 했을때는 map의 전체 결과값을 저장하고 이후에 filter를 실행하는데
asSequence()를 사용하면 map의 전체 결과값을 저장하고 filter를 수행하는것이 아니라,
개별적으로 map과 filter를 병렬적으로 수행하기 때문에, 중간 과정에서 변수를 저장하지 않아 속도나 메모리 측면에서 훨씬 좋은 성능을 얻을 수 있습니다.

하지만 filter() 등은 인라인 함수로 설계되어 있는데, 시퀀스를 사용하면 람다식을 저장하는 객체로 표현되기 때문에 인라인되지 않아 작은 컬렉션에는 오히려 좋지 않습니다.

참고

서적 : Do it! 코틀린 프로그래밍

Comments