코틀린 (Kotlin) 시퀀스 사용하기(지연 계산)
지연 계산
아래 코드는 map과 filter 를 호출합니다.그러나 map 에서 리스트를 생성하고 filter 에서도 리스트를 새로 생성하기때문에 데이터가 많은 경우 효율적이지 않습니다.
people.map(Person::name).filter { it.startsWith("A") }
시퀀스(sequence)
큰 데이터를 연산할 때는 중간 리스트를 생성하지 않는 시퀀스를 사용하는 것이 효율적입니다.시퀀스는 아래 연산처럼 중간 연산에서는 아무것도 실행되지 않습니다.
listOf(1, 2, 3, 4)
.asSequence()
.map { it * it }
.filter { it % 2 == 0 }
.asSequence()
.map { it * it }
.filter { it % 2 == 0 }
시퀀스는 최종 연산이 호출될 때 실행됩니다.
listOf(1, 2, 3, 4)
.asSequence()
.map { it * it }
.filter { it % 2 == 0 }
.toList() //최종 연산
.asSequence()
.map { it * it }
.filter { it % 2 == 0 }
.toList() //최종 연산
시퀀스의 실행
시퀀스의 연산은 각 값에 대해 순차적으로 적용됩니다.
listOf(1, 2, 3, 4)
.asSequence()
.map { it * it }
.find { it > 3 }
.asSequence()
.map { it * it }
.find { it > 3 }
위 코드의 경우 실행 순서는 다음과 같습니다.
- list(1) -> map(1*1) -> find(1>3) -> list(2) -> map(2*2) -> find(4>3) -> 종료
이처럼 시퀀스는 중간 리스트를 만들지않고 값을 순차적으로 계산하기때문에 특정 조건이 만족하는경우 중간에 이터레이션을 종료할 수 있습니다.
시퀀스가 없는 경우에는 map 리스트(1,4,9,10) 을 생성하고 map 리스트 값에서 find 로 4를 찾아 반환할 것이기 때문에 불필요한 중간 리스트가 생성됩니다.
시퀀스에서 map과 filter 순서 차이
시퀀스를 사용할 때 map과 filter 를 어떤 순서로 적용하느냐에 따라 성능이 달라질 수 있습니다.
map 다음 filter 를 사용하면 map 에서 모든 원소를 이터레이션합니다.
filter 다음 map 을 사용하면 filter 에서 filter(it.length < 4) 와 같이 조건에 만족하는 값만 이터레이션하기 때문에 더 효율적으로 사용할 수 있습니다.
시퀀스 만들기
asSequence() 없이 직접 시퀀스를 만들 수 있습니다.
generateSequence() 함수로 첫 번째 값을 지정하고 다음 원소를 구하는 식을 지정하면 됩니다.
그리고 sum(), any(), find() 등으로 최종 연산을 지정하면 원하는 값을 얻을 수 있습니다.
generateSequence() 함수로 첫 번째 값을 지정하고 다음 원소를 구하는 식을 지정하면 됩니다.
그리고 sum(), any(), find() 등으로 최종 연산을 지정하면 원하는 값을 얻을 수 있습니다.
//sequence 는 함수를 한개 원소씩 순차적으로 실행하여 조건에 맞으면 그대로 종료
val naturalNumbers = generateSequence(0) { it + 1} //0부터 시작
//여기까지도 아무것도 실행안됨
val numbersTo100 = naturalNumbers.takeWhile { it <= 100 }
//sum() 은 최종연산
numbersTo100.sum()
//시퀀스로 파일 탐색하기
fun File.isinsideHiddenDirectory() = //확장함수
generateSequence(this) {
it.parentFile
}.any {
it.isHidden
//find 함수로 원하는 디렉터리를 찾을 수도 있음
}
val file = File("/storage/self/primary/Download/mug_obj_154719227478915505.png")
file.isinsideHiddenDirectory()
val naturalNumbers = generateSequence(0) { it + 1} //0부터 시작
//여기까지도 아무것도 실행안됨
val numbersTo100 = naturalNumbers.takeWhile { it <= 100 }
//sum() 은 최종연산
numbersTo100.sum()
//시퀀스로 파일 탐색하기
fun File.isinsideHiddenDirectory() = //확장함수
generateSequence(this) {
it.parentFile
}.any {
it.isHidden
//find 함수로 원하는 디렉터리를 찾을 수도 있음
}
val file = File("/storage/self/primary/Download/mug_obj_154719227478915505.png")
file.isinsideHiddenDirectory()
*개인적으로 코틀린을 공부하면서 정리한 자료입니다. 수정 사항 및 이슈가 있는 경우 메일 부탁드립니다.
댓글
댓글 쓰기