일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Design Pattern
- builderPattern
- a
- 함수형프로그래밍
- Kotlin
- 코틀린
- 프로토타입 패턴
- ㅓ
- 싱글톤
- 빌터패턴
- 추상팩토리패턴
- 옵저버 패턴
- factory method
- 추상 팩토리
- F
- 디자인패턴 #
- Observer Pattern
- PrototypePattern
- 디자인패턴
- ㅋㅁ
- Functional Programming
- 팩토리 메소드
- Abstract Factory
- Singleton
- designPattern
- r
- El
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
람다로 프로그래밍 (지연계산(Lazy) 컬렉션 연산) 본문
컬렉션 함수를 연쇄하면서 매 단계마다 계산 중간결과를 새로운 컬렉션에 임시로 담는 건 너무 비효율적이다.
시퀀스를 사용하면 중간 임시 컬렉션을 사용하지 않고도 컬렉션 연산을 연쇄할 수 있다.
fun main() {
val people = listOf( Person("Alice", 27), Person("Bob", 31), Person("kim", 19),
Person("hong", 25), Person("park", 12))
people.map { it.name }.filter { it.startsWith("A") }
people.asSequence()
.map { it.name }
.filter { it.startsWith("A") }
.toList()
}
원소가 적은 경우는 큰 차이가 없겠지만 원소가 많은 경수 성능 차이가 현저하게 난다.
Sequence
- 코틀린의 지연 계산 시퀀스는 Sequence 인터페이스에서 시작한다.
- 이 인터페이스는 단지 한 번에 하나씩 열거될 수 있는 원소의 시퀀스를 표현한다.
- Sequence에는 iterator라는 단 하나의 메서드가 있다. 이를 통해 원소 값을 얻을 수 있다.
Sequence 인터페이스 강점은 그 인터페이스 위에 구현된 연산이 계산을 수행하는 방법 때문이다.
시퀀스의 원소는 필요할 때 비로소 계산된다. 따라서 중간처리 결과를 저장하지 않고도 연산을 연쇄적으로 하되 효율적이다.
asSequence 함수는 어떤 컬렉션이든 시퀀스로 변경 가능하며 시퀀스를 다시 다른 컬렉션으로 변경 가능하다.
Sequence 연산 실행: 중간 연산과 최종 연산
시퀀스에 대한 연산은 중간 연산과 최종 연산으로 나뉜다.
중간 연산은 최초 시퀀스의 원소를 변환하는 법을 안다 최종연산은 결과를 반환한다.
people.asSequence()
<중간 연산> - 중간 연산은 최종 연산을 하기 전까지 항상 지연된다.
. { map.name }
. filter { it.startsWith("A") }
<최종연산> - 모든 연산이 실행된다.
. toList()
people.asSequence()
.map { println("$it") ; it.name }
.filter {println("$it"); it.startsWith("A") }
people.asSequence()
.map { println("$it") ; it.name }
.filter {println("$it"); it.startsWith("A") }
.toList()
1번째는 최종 연산이 없기 때문에 어느 것도 출력되지 않는다.
연산의 수행 순서
fun main() {
val people = listOf( Person("Alice", 27), Person("Bob", 31), Person("kim", 19),
Person("hong", 25), Person("park", 12))
people.map { println("$it"); it.name }.filter {println("$it"); it.startsWith("A") }
people.asSequence()
.map { println("$it") ; it.name }
.filter {println("$it"); it.startsWith("A") }
.toList()
}
일반 컬렉션 함수는 모든 원소를 처리하고 다음 그 중간 컬렉션을 가지고 다시 모든 원소에 대한 연산을 진행한다.
하지만 시퀀스의 경우 모든 연산은 각 원소별로 순차적으로 진행한다.
즉 첫 번째 원소가 모든 연산을 다처리하고 두 번째 원소가 모든 연산을 처리하고... 이 순서다.
따라서 각 원소에 대한 연산을 처리하다 원하는 결과가 도출되면 이후 원소에 대해서는 변환이 이루어지지 않을 수도 있다.
val list = listOf(1, 2, 3, 4 )
println("Sequence 연산")
list.asSequence()
.map { println(it); it * it }
.find{ println(it); it > 3}
println("일반 연산")
list .map { println(it); it * it }.find{ println(it);it > 3}
이미 조건에 만족하는 3 이상의 수를 찾았기 때문에 시퀀스는 뒤의 원소들에 대한 연산을 하지 않지만
일반 연산은 일단 모든 원소를 맵 연산을 시킨 후 3 이상의 수를 찾고 연산을 멈춘다
컬렉션의 연산의 순서 또한 성능에 영향을 준다.
fun main() {
val people = listOf(Person("Alice", 27), Person("Bob", 31), Person("Charles", 31),
Person("Dan", 21))
println("map -> filter:")
println(
people.asSequence()
.map { println("$it"); it.name }
.filter {println("$it"); it.length < 4}
.toList()
)
println("filter -> map:")
println(
people.asSequence()
.filter { println("${it.name}"); it.name.length < 4}
.map { println("$it"); it.name }
.toList()
)
}
map을 먼저 연산하면 각 원소를 1번씩은 변환한다. 하지만 filter를 먼저 하면 부적절한 원소를 먼저 제외하기 때문에 이후 map연산에서 그 원소는 제외된다.
* 자바 스트림과 코틀린의 시퀀스
자바 8의 스트림과 코틀린의 시퀀스는 매우 비슷한 개념이지만 안드로이드에서 예전 버전 자바를 사용하는 경우 스트림을 사용할 수 없기 때문에 코틀린의 시퀀스를 사용하면 된다. 만약 자바 8을 사용한다면 필요에 따라 선택하면 된다.
시퀀스 만들기
generateSequence 함수를 사용한다.
이 함수는 이전의 원소를 인자로 받아 다음 원소를 계산한다
0을 넣고 그이후 1씩더해가면서 시퀀스를 생성하였다.
100이하일때 까지 진행한다.
그리고 합산한다.<최종연산>
fun main() {
val naturalNumbers = generateSequence(0) { it+1 }
val numberTo100 = naturalNumbers.takeWhile { it <= 100 }
println(numberTo100.sum())
}
File 클래스의 확장함수를 생성한다.
현재 파일 위치를 주고 다음 원소를 부모파일 위치로한다.
숨긴 파일이 있는지 찾는다.
fun File.isInsideHiddenDirectory() =
generateSequence(this){it.parentFile}.any { it.isHidden }
fun main() {
val file = File("filePath")
println(file.isInsideHiddenDirectory())
}
'Kotlin in Action > 코틀린 기초' 카테고리의 다른 글
코틀린 타입 시스템 ( Null 가능성) (0) | 2020.08.19 |
---|---|
람다로 프로그래밍 (자바 함수형 인터페이스 사용) (0) | 2020.08.18 |
람다로 프로그래밍(컬렉션 함수형 API) (0) | 2020.08.16 |
람다로 프로그래밍 (0) | 2020.08.16 |
클래스 객체 인터페이스(Object 키워드 : 클래스 선언과 인스턴스 생성) (0) | 2020.08.14 |