자바(Java)는 컬렉션(Collection)에 저장된 데이터를 하나씩 순회할 수 있도록 Iterator와 ListIterator라는 두 가지 인터페이스를 제공합니다. 두 이터레이터의 내부 구현 방식은 서로 다르지만, 컬렉션의 요소를 안전하게 하나씩 처리한다는 근본적인 목적은 동일합니다.
Iterator란 무엇인가?
java.util.Iterator는 Set, List, Queue, Deque 등 Collection 프레임워크의 모든 구현체에서 사용할 수 있는 표준 순회 인터페이스입니다. iterator() 메서드를 호출하여 객체를 생성하며, hasNext(), next(), remove() 세 가지 핵심 메서드를 제공합니다.
ListIterator란 무엇인가?
java.util.ListIterator는 Iterator를 상속해 기능을 확장한 인터페이스로, ArrayList나 LinkedList처럼 List 인터페이스를 구현한 클래스에서만 사용할 수 있습니다. 순방향뿐 아니라 역방향 순회가 가능하고, 요소의 추가(add())·수정(set())·삭제(remove()) 및 인덱스 조회(nextIndex(), previousIndex()) 등 더욱 풍부한 기능을 제공합니다.
Iterator와 ListIterator의 주요 차이점
| 번호 | 구분 기준 | Iterator | ListIterator |
|---|---|---|---|
| 1 | 적용 범위 | 컬렉션 종류에 관계없이 Set, List, Queue, Map 등 모든 컬렉션을 순회할 수 있습니다. | ArrayList, LinkedList 등 List 인터페이스를 구현한 클래스에만 사용할 수 있습니다. |
| 2 | 객체 생성 | Collection 인터페이스의 iterator() 메서드를 호출하여 생성합니다. | List 인터페이스의 listIterator() 메서드를 호출하여 생성합니다. |
| 3 | 순회 방향 | 순방향(forward) 단방향 순회만 가능합니다. | 순방향과 역방향(backward) 양방향 순회가 모두 가능합니다. |
| 4 | 요소 삭제 | remove() 메서드로 직전에 반환한 요소만 삭제할 수 있으며, 임의 위치 삭제는 불가능합니다. | remove() 메서드로 순회 중 요소를 삭제할 수 있습니다. |
| 5 | 요소 추가 | 요소 추가 기능이 없습니다. 순회 중 컬렉션을 직접 수정하면 ConcurrentModificationException이 발생합니다. | add() 메서드로 순회 중 언제든지 요소를 추가할 수 있습니다. |
| 6 | 요소 수정 | 요소 수정 기능이 없습니다. | set() 메서드로 순회 중 언제든지 요소를 교체할 수 있습니다. |
| 7 | 인덱스 조회 | 현재 순회 중인 요소의 인덱스를 알 수 없습니다. | nextIndex(), previousIndex() 메서드로 순회 중 언제든지 인덱스를 확인할 수 있습니다. |
Iterator vs ListIterator 예제 코드
JavaTester.java
import java.io.*;
import java.util.*;
public class JavaTester {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// Iterator 순회
Iterator<Integer> itr = list.iterator();
System.out.println("Iterator 순회:");
while (itr.hasNext()) {
System.out.print(itr.next() + " ");
}
System.out.println();
// ListIterator 순방향 순회
ListIterator<Integer> i = list.listIterator();
System.out.println("ListIterator 순방향 순회:");
while (i.hasNext()) {
System.out.print(i.next() + " ");
}
System.out.println();
// ListIterator 역방향 순회
System.out.println("ListIterator 역방향 순회:");
while (i.hasPrevious()) {
System.out.print(i.previous() + " ");
}
}
}
실행 결과
Iterator 순회: 1 2 3 4 5 ListIterator 순방향 순회: 1 2 3 4 5 ListIterator 역방향 순회: 5 4 3 2 1
정리: 어떤 것을 사용해야 할까?
- Iterator: Set, Queue, Map 등 컬렉션 종류에 상관없이 단순 읽기·삭제 위주의 순방향 순회가 필요할 때 적합합니다.
- ListIterator: List에서 양방향 순회가 필요하거나, 순회 도중 요소를 추가·수정하거나 현재 위치의 인덱스가 필요할 때 적합합니다.
단, 두 이터레이터 모두 fail-fast 방식으로 동작하므로, 순회 중 이터레이터가 아닌 방법으로 컬렉션의 구조를 변경하면 ConcurrentModificationException이 발생할 수 있다는 점을 반드시 기억해야 합니다.