컬렉션 프레임워크에서, Iterator 를 사용해서 객체를 순회하고 값을 확인할 수 있다. 예시를 보자.
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 결과는 1 2 3 순서대로 출력.
Iterator 는 뭐고, iterator() 메소드는 어떻게 호출되는걸까?
Iterable 인터페이스
자바에서 Iterator 인터페이스는 컬렉션의 요소를 순차적으로 접근하는 방법을 제공하는 인터페이스이다.
아래 도식도를 보자.
컬렉션 인터페이스는 Iterable 인터페이스를 상속하고, Iterable 인터페이스에는 iterator() 메소드가 존재한다.
이 iterator 메소드는 Iterator 인터페이스를 반환한다. 그리고, 이 Iterator 인터페이스가 hasNext(), next(), remove() 와 같은 컬렉션 요소에 접근하는 주요 메소드를 가지고 있다.
모든 컬렉션 프레임워크는 이 Iterable 인터페이스를 상속하고 있기에 iterator() 메소드를 호출해서 Iterator 를 사용할 수 있는 것이다.
그리고 iteartor()의 구현은 LinkedList, HashSet, PriorityQueue 와 같은 실제 구현체들에서 메소드를 구현해서 사용하게 된다.
PriorityQueue 의 코드를 확인해보면
내부적으로 선언한 Itr 클래스를 iterator() 메소드에서 반환한다.
Itr 클래스는 Iterator 인터페이스를 상속하고 거기서 구현해야 하는
hasNext(), next(), remove() 메소드를 구현하고 있다.
LinkedList를 코드를 살펴보면,
LinkedList 는 AbstractSequentialList 를 상속하고, 해당 인터페이스에서 listIterator() 메소드를 호출해서 처리하고 있다.
이와 같이 컬렉션에 맞게 iterator 메소드가 다르게 구현되고 있는거를 확인할 수 있다.
Iterator 인터페이스
그래서 Iterator는, 컬렉션을 순회하는 포인터라고 생각하면 된다.
Iterator 는 일방향 순회만 가능하고, 요소를 한 번 순회하면 다시 이전으로 돌아갈 수 없다는 특징이 있다.
Iterator는 3개의 메소드를 가지고 있다.
- boolean hasNext(): 다음 요소가 있으면 true를 반환, 없으면 false.
- E next(): 다음 요소를 반환하고 커서를 다음 위치로 이동.
- void remove(): 현재 위치의 요소를 컬렉션에서 제거.
ListIterator 인터페이스
ListIterator 는 List 인터페이스를 구현한 컬렉션에서 사용가능하며, Iterator 에서 조금 더 확장된 버전으로 보면 된다.
기존의 Iterator 과 다른점은, 양방향 순회가 가능하며 리스트의 요소를 수정할 수 있다는 점이다.
추가적으로 4개의 주요 메소드가 있다.
- boolean hasPrevious(): 이전 요소가 있으면 true를 반환.
- E previous(): 이전 요소를 반환하고 커서를 이전 위치로 이동.
- void set(E e): 마지막으로 반환된 요소를 주어진 요소로 변경.
- void add(E e): 주어진 요소를 현재 위치에 추가.
사용예시
- LinkedList 사용시에는 필수로 사용이 되어야 한다. 특정 위치에 Iterator(포인터) 를 두고, 값의 삽입, 수정, 삭제등을 효율적으로 할 수 있다. 만약 Index 로 접근한다면 해당 자료구조를 사용하는 이유가 없다.
- Set 과 같이 인덱스로 접근할 수 없는경우에 요소를 확인하는데에 사용할 수 있다. (이는 enhanced for loop 로 표현도 가능하다.)
참조
'자바' 카테고리의 다른 글
[Spring] @Bean 메소드 파라미터 자동주입 (0) | 2024.10.06 |
---|---|
[Java] 자바 제네릭, Generic 문법 (1) | 2023.10.03 |