반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 인공지능
- 프로그래밍언어
- 보안
- 프로그래밍
- 자바스크립트
- 컴퓨터공학
- 웹개발
- 버전관리
- Yes
- 네트워크보안
- 머신러닝
- 네트워크
- 사이버보안
- 빅데이터
- 데이터분석
- 소프트웨어
- 데이터구조
- 디자인패턴
- 컴퓨터과학
- 컴퓨터비전
- 소프트웨어공학
- 클라우드컴퓨팅
- 자료구조
- 알고리즘
- springboot
- 데이터베이스
- I'm Sorry
- 딥러닝
- 데이터과학
- 파이썬
Archives
- Today
- Total
스택큐힙리스트
Iterator 패턴 – 컬렉션 속을 우아하게 누비는 비결 본문
반응형
“for-each 없이도, 내부 구조 몰라도, 끝까지 한 번에!”
왜 Iterator인가?
코드가 커질수록 자료구조가 제각각입니다. 배열, 연결 리스트, 트리, 그래프…
Iterator 패턴은 데이터 구조를 감추고 “다음 요소를 주세요” 라는 단일 프로토콜로 순회(Traversal)를 통일합니다.
즉, 컬렉션 구현을 몰라도 같은 방식으로 next() / hasNext()만 호출하면 끝. 책임이 깨끗하게 나뉘니 테스트·유지보수·확장성이 모두 좋아집니다.
핵심 아이디어
- Iterable(집합) – “Iterator를 하나 주세요!”를 요청받으면 해당 컬렉션에 맞는 반복자를 반환
- Iterator(반복자) – 순회 상태를 보유하며 hasNext()와 next()를 통해 한 걸음씩 이동
- 클라이언트 – 내부 구조를 몰라도 동일한 API로 데이터에 접근
Kotlin 예제 – 깊이 우선 트리 순회
// 트리 노드
data class Node<T>(val value: T, val children: List<Node<T>> = emptyList())
// Iterator 구현
class DepthFirstIterator<T>(start: Node<T>) : Iterator<T> {
private val stack = ArrayDeque<Node<T>>().apply { push(start) }
override fun hasNext() = stack.isNotEmpty()
override fun next(): T {
val node = stack.removeLast()
node.children.reversed().forEach { stack.addLast(it) } // DFS
return node.value
}
}
// Iterable 래퍼
class Tree<T>(private val root: Node<T>) : Iterable<T> {
override fun iterator(): Iterator<T> = DepthFirstIterator(root)
}
// 사용
fun main() {
val tree = Tree(
Node(1, listOf(Node(2), Node(3, listOf(Node(4), Node(5)))))
)
for (v in tree) print("$v ") // 1 2 3 4 5
}
- 자료구조 비공개: Tree 외부에서는 스택·자식 리스트를 전혀 알 필요가 없습니다.
- 전략 교체: 필요하면 BreadthFirstIterator만 새로 만들어 넣으면 끝 – OCP 준수.
언제 빛을 발하나?
- 다양한 컬렉션 타입을 일괄 처리할 때 (e.g., 레거시 리스트 + 새 큐 혼재)
- 복잡한 순회 로직을 캡슐화해 비즈니스 코드에서 분리하고 싶을 때
- 동일 컬렉션에 여러 순회 방식(정방향·역방향·필터링)을 런타임에 바꿔야 할 때
실전 팁
- Kotlin/JVM에선 Iterable·Sequence가 이미 Iterator 패턴의 정석 구현이므로 직접 구현보다 확장(커스텀 iterator()·asSequence()) 방식이 간단합니다.
- 병렬 처리가 필요하면, 순회 상태를 공유하지 않는 클론 가능한 Iterator를 따로 두어야 Race Condition을 피할 수 있습니다.
- “한 번만 순회해야” 하는 스트림(예: 네트워크 응답)은 forEachRemaining 대신 코루틴 Flow를 고려해 I/O 차단을 줄일 수 있습니다.
반응형
'개발' 카테고리의 다른 글
Mediator 패턴: 복잡한 객체 의존을 한 방에 정리하기 (2) | 2025.07.29 |
---|---|
Kotlin Sequence 내부 구현으로 배우는 Lazy Iterator 원리 (1) | 2025.07.29 |
책임 연쇄 vs 데코레이터 — 헷갈리는 두 패턴, 결정적 차이를 콕 짚다 (1) | 2025.07.28 |
책임을 넘겨라! Chain of Responsibility 한방 정복 (2) | 2025.07.28 |
명령을 객체로! 커맨드 패턴으로 유연한 실행 로직 만들기 🚀 (2) | 2025.07.28 |
Comments