일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |
- dp
- 브루트포스
- 2023 KAKAO BLIND RECRUITMENT
- 구현
- 자바
- 프로그래머스
- const
- 삼성SW역량테스트
- kotlin
- 2022 KAKAO BLIND RECRUITMENT
- js
- 컴퓨터비전
- 누적합
- 코틀린
- 동적계획법
- VAR
- 유니온파인드
- 2021 KAKAO BLIND RECRUITMENT
- 컴퓨터 비전
- JavaScript
- Lv3
- level3
- 호이스팅
- BFS
- 2018 KAKAO BLIND RECRUITMENT
- 자바스크립트
- java
- lv2
- 백준
- level2
- Today
- Total
코드를 느껴바라
kotlin : Sequence 뭐가 다르고 왜 쓰는 건지? 본문
개발하면서 이런 코드 한 번쯤은 봤을 거다.
val result = sequenceOf(1, 2, 3).map { it \* 2 }
처음 보면 listOf랑 비슷하게 생겼는데, sequenceOf...? 뭐지? 리스트랑 뭐가 다른 거지? 싶다. 나도 그랬다. 그냥 List 쓰면 안 되나? 싶어서 한동안은 신경도 안 썼는데, 이거 은근히 잘 쓰면 성능 최적화에 꽤 유리한 도구다.
Sequence가 뭐냐면
Kotlin에서 Sequence는 게으르게 계산(lazy evaluation)되는 컬렉션이다.
쉽게 말하면, List처럼 값을 들고 있는 게 아니라, 필요할 때마다 원소를 하나씩 꺼내서 계산하는 구조라고 보면 된다. 그러니까 "결과를 지금 당장 다 만들지 않고, 쓰는 시점에서 하나씩 만든다"는 개념.
예를 들어, 이런 코드가 있다고 하자.
val doubled = sequenceOf(1, 2, 3).map { it \* 2 }
이건 map까지 적었어도 실제로 it * 2 계산이 수행되지 않는다. toList() 같은 걸로 끝을 맺어줘야 진짜 연산이 시작된다. 이게 바로 lazy한 특징이다.
근데 왜 굳이 Sequence를 써?
이게 진짜 핵심이다.
"그냥 리스트로 map하고 filter 하면 되잖아? 굳이?"
나도 그렇게 생각했는데, 몇 가지 경우에 Sequence는 생각보다 큰 차이를 만든다.
1. 중간 계산이 많을 때
kotlin
복사편집
listOf(1, 2, 3, 4, 5) .map { it * 2 } .filter { it > 5 } .take(1)
리스트는 기본적으로 한 단계씩 전체를 다 계산한다.
그래서 위 코드에서는:
- 먼저 map을 전체 돌고,
- 그 결과에 filter를 전체 적용하고,
- 마지막에야 take(1)이 적용된다.
근데 만약 첫 번째로 걸린 값이 정답이라면? 나머지 값까지 다 계산하는 건 낭비다.
→ Sequence는 이걸 방지해준다. 원소 하나당 map → filter → take 순으로 한 번에 평가하고, 조건이 만족되면 거기서 끝난다. 즉, 불필요한 계산을 하지 않는다.
2. 무한 시퀀스도 가능
kotlin
복사편집
val infinite = generateSequence(1) { it + 1 } // 1, 2, 3, ... val result = infinite.filter { it % 2 == 0 }.take(5).toList()
리스트로는 절대 못 하는 거다. 무한 반복문처럼 쭉 생성되는 데이터에서도 Sequence는 필요한 만큼만 뽑아서 쓸 수 있다.
리스트 vs 시퀀스, 어떻게 다른지?
실제 연산 로그를 비교해보자. 다음 두 코드 비교:
List
kotlin
복사편집
val list = listOf(1, 2, 3, 4, 5) .map { println("map $it"); it * 2 } .filter { println("filter $it"); it > 5 } .take(1)
출력:
python
복사편집
map 1 map 2 map 3 map 4 map 5 filter 2 filter 4 filter 6 filter 8 filter 10
무조건 map 5번 → filter 5번 = 총 10번 연산
Sequence
kotlin
복사편집
val seq = sequenceOf(1, 2, 3, 4, 5) .map { println("map $it"); it * 2 } .filter { println("filter $it"); it > 5 } .take(1) .toList()
출력:
python
복사편집
map 1 filter 2 map 2 filter 4 map 3 filter 6
→ map 3번, filter 3번만 수행하고 끝.
조건에 맞는 값 하나 찾자마자 나머지는 연산조차 하지 않는다.
언제 쓰면 좋냐? 🤔
상황Sequence 쓰는 거 추천
데이터 양이 아주 많거나 무한 | ✅ |
---|---|
중간에 take, find, first 등으로 끊을 수 있을 때 | ✅ |
map, filter, flatMap 등 체인이 길어질 때 | ✅ |
리스트 한두 개만 돌리는 간단한 코드 | ❌ 오히려 List가 더 직관적 |
마무리
Kotlin에서 Sequence는 자주 안 쓰이지만, 알고 있으면 확실히 효율적인 코드를 짤 수 있는 도구다. 특히 필터링과 조건 처리할 때, 불필요한 연산을 줄일 수 있다는 점에서 리스트보다 훨씬 똑똑하다.
"내 코드, 요즘 느린데?" 싶을 때 한 번쯤 asSequence() 붙여보고 결과 비교해보면 좋다. 작은 차이가, 큰 차이를 만든다.
'개발 > 앱(Android)' 카테고리의 다른 글
kotlin : 클래스(Class)의 생성자 (0) | 2025.04.20 |
---|---|
kotlin : field란? (5) | 2025.03.20 |
kotlin : 코틀린 변수 및 상수 (0) | 2025.03.13 |