Java에서 Iterator와 Spliterator는 모두 컬렉션(Collection)의 요소를 순회하기 위해 사용되는 인터페이스입니다. 하지만 두 인터페이스는 도입 배경과 동작 방식에서 중요한 차이를 보이며, 특히 멀티코어 환경에서의 성능 최적화 측면에서 그 차이가 두드러집니다.
Spliterator란 무엇인가?
Spliterator(Split + Iterator)는 Java 8에서 병렬 처리(Parallelism)를 지원하기 위해 새롭게 도입된 인터페이스입니다. 주어진 데이터 집합을 여러 조각으로 분할(split)한 뒤, 서로 독립적인 스레드에서 각 조각을 동시에 처리할 수 있도록 설계되었습니다.
Spliterator는 요소를 병렬 방식뿐만 아니라 순차적(Sequential) 방식으로도 순회할 수 있으며, Stream API와 함께 사용될 때 특히 강력한 성능을 발휘합니다.
Spliterator의 주요 메서드
- trySplit() – 데이터 집합을 여러 조각으로 분할하고, 분할된 부분을 담당하는 새로운 Spliterator를 반환합니다.
- tryAdvance() – Iterator의 hasNext()/next() 메서드에 해당하며, 다음 요소가 존재하면 해당 요소에 지정된 작업을 수행합니다.
- getExactSizeIfKnown() – 크기를 미리 알 수 있는 경우 데이터 집합의 정확한 크기를 반환합니다.
- forEachRemaining() – 남은 모든 요소에 대해 지정된 작업을 한 번에 수행합니다.
Iterator vs Spliterator 핵심 차이점
| 번호 | 구분 기준 | Iterator | Spliterator |
|---|---|---|---|
| 1 | 기본 용도 | 컬렉션의 요소를 순회하는 데 사용됩니다. | 컬렉션뿐만 아니라 Stream에서도 사용할 수 있습니다. |
| 2 | 대량 처리(Bulk Operation) | 요소를 하나씩만 순회할 수 있습니다. | 요소를 일괄(bulk) 단위로 순회할 수 있습니다. |
| 3 | 순차 / 병렬 처리 | 순차적(Sequential) 방식으로만 순회 가능합니다. | 순차적 방식과 병렬(Parallel) 방식 모두 지원합니다. |
| 4 | 외부 / 내부 반복자 | 외부 반복(External Iteration) 방식을 사용합니다. 개발자가 직접 순회를 제어합니다. | 내부 반복(Internal Iteration) 방식을 사용합니다. 순회 제어를 프레임워크에 위임합니다. |
Spliterator 예제 코드
다음은 trySplit()을 사용해 리스트를 두 개의 조각으로 나눈 뒤, 각각 순회하는 예제입니다.
public class Main {
public static void main(String args[]) {
List<Integer> listOfInteger = new ArrayList<>();
listOfInteger.add(78);
listOfInteger.add(10);
listOfInteger.add(20);
listOfInteger.add(30);
Spliterator<Integer> s = listOfInteger.spliterator();
Spliterator<Integer> s1 = s.trySplit();
System.out.println("Traverse First Half");
s.forEachRemaining(System.out::println);
System.out.println("Traverse Second Half");
s1.forEachRemaining(System.out::println);
}
}
마무리 정리
단순히 컬렉션을 순서대로 하나씩 읽는 것이 목적이라면 기존의 Iterator로 충분합니다. 하지만 대용량 데이터를 여러 스레드로 나누어 병렬로 처리해야 하는 상황이라면 Spliterator가 훨씬 적합한 선택입니다. Java 8 이상의 환경에서 Stream API의 parallelStream()을 활용한다면, 내부적으로 Spliterator가 자동으로 데이터를 분할하여 병렬 처리를 수행해 줍니다.