반응형

[JAVA] 자바 Iterator와 ListIterator 사용법


자바에서는 Collection 인터페이스를 구현한 자료구조인 ArrayList, LinkedList, HashSet, TreeSet 등의 요소를 하나씩 반복하여

모든 요소를 확인할 수 있는 Iterator (단방향) ListIterator(양방향)가 있습니다.

 


Iterator 구현도

 

인터페이스가 추상메서드를 갖고 있다면 해당 인터페이스를 구현하는 클래스는 모두 해당 메서드의 구현부를 작성해야 합니다.

 

Iterator는 iterator()라는 함수명을 갖고 있는 추상 메서드가 반환을 합니다.

iterator() 추상 메서드의 위치는 Iterable이라는 인터페이스에서 작성을 해뒀습니다.

결국 Iterable을 구현한 모든 클래스는 iterator()라는 함수의 구현부를 작성해야합니다.

 

Collection 인터페이스

Collection 인터페이스가 Iterable를 상속받았습니다.

그래서 Collection을 구현한 자료구조 API는 iterator()함수를 구현을 해놨습니다.

실제 구현부는 ArrayList, LinkedList, HashSet, TreeSet 와 같은 실제 인스턴스를 생성하는 클래스에서 구현을 합니다.

설계 방식은 전부 다르므로 Iterator를 통해 요소를 가져오고 삭제하는 과정도 따로 작업을 해놨습니다.

 

iterator()를 호출하면 Itr이라는 내부 클래스명으로 Iterator를 상속받고, 객체를 생성해서 돌려줍니다.

iterator()의 반환인 Iterator 인터페이스가 Collection 순회를 돕는 hasNext(), next(), remove()를 구현하도록 하고 있습니다.

 

Iterator를 상속했으니, Iterator it = list.iterator() 와 같이 사용합니다.

 

주의점

List는 저장 순서를 유지하기 때문에 iterator를 사용하면 저장 순서를 유지하며 요소를 확인할 수 있지만,

Set은 저장 순서를 유지하지 않기 때문에 저장 순서대로 요소를 확인할 수 없습니다.

 

인터페이스 구현 순서

  1. Iterable
  2. Collection
  3. List, Set
  4. ArrayList, LinkedList, HashSet, TreeSet 등

 

아래 사진은 ArrayList 내부에 Iterator를 반환하는 iterator() 함수의 작성 내용입니다.

 

ArrayList iterator()

iterator()의 직접적인 구현은 ArrayList, LinkedList, HashSet, TreeSet에 작성하는 걸 확인할 수 있습니다.

iterator() 함수를 호출하게 되면 Itr() 인스턴스를 생성하여 return합니다.

Itr은 내부 클래스로 Iterator 인터페이스의 추상 메서드 hasNext(), next(), remove() 를 모두 구현합니다.

Iterator의 메서드는 JAVA API에서 확인할 수 있습니다.

 

https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Iterator.html

 

Iterator (Java SE 15 & JDK 15)

Type Parameters: E - the type of elements returned by this iterator All Known Subinterfaces: EventIterator, ListIterator , PrimitiveIterator , PrimitiveIterator.OfDouble, PrimitiveIterator.OfInt, PrimitiveIterator.OfLong, XMLEventReader All Known Implement

docs.oracle.com

 

 


Iterator, ListIterator 사용법

 

Iterator의 구현도는 복잡하지만 실제 사용하려는 프로그래머 입장에서는 iterator의 사용은 아주 단순합니다.

주의할 점은 Iterator, ListIterator의 cursor 위치는 시작할 때 맨 앞 요소 그 앞에 있습니다.

cursor의 위치는 요소를 가리키고 있는 것이 아니라 요소와 요소 사이에 있다라고 생각하시면 됩니다.

 

 

Iterator의 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;
 
public class IteratorTest {
    public static void main(String[] args) {
        ArrayList<Integer> arr_list = new ArrayList<>();
        arr_list.add(1);
        arr_list.add(2);
        arr_list.add(3);
        arr_list.add(4);
 
        // Iterator
        Iterator<Integer> itr = arr_list.iterator();
 
        while(itr.hasNext()){
            int n = itr.next();
            System.out.print(n + " ");
            if(n == 2)
                itr.remove();
        }
        System.out.println();
        System.out.println(arr_list);
    }
}
cs

 

12줄) iterator() 함수는 Iterator 인터페이스 return으로 받을 수 있는 Iterator를 Type으로 선언하여 사용해주시면 됩니다.

14줄) hasNext() 함수는 다음 요소가 있다면 true, 없다면 false를 return 합니다. 마지막 요소까지 확인할 수 있습니다.

15줄) next() 함수는 cursor 위치를 오른쪽으로 옮긴 후 왼쪽 요소를 반환합니다. cursor 위치는 요소와 요소 사이입니다.

* cursor가 지나온 요소를 반환한다고 생각하시면 됩니다.

18줄) remove() 함수는 next() 함수의 반환 값을 삭제합니다. 실제 ArrayList에도 영향을 미칩니다.

 

결과

 

 

 

ListIterator의 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.*;
 
public class ListIteratorTest {
    public static void main(String[] args) {
        ArrayList<Integer> arr_list = new ArrayList<>();
        arr_list.add(1);
        arr_list.add(2);
        arr_list.add(3);
        arr_list.add(4);
 
        // ListIterator
        ListIterator<Integer> it = arr_list.listIterator();
        System.out.print(it.next()+ " ");
        System.out.print(it.next()+ " ");
        System.out.print(it.previous()+ " ");
 
        System.out.println();
        System.out.println(arr_list);
 
    }
}
cs

 

ListIterator는 Iterator와 사용방법이 비슷합니다. 대신 ListIterator는 이전 요소로 되돌아갈 수 있습니다.

 

13, 14줄) it.next()를 부르면 다음 요소로 넘어갑니다. 15줄) it.previous() 호출하면 이전 요소로 되돌아갈 수 있습니다.

이런 식으로 양방향으로 이동 가능한 것이 ListIterator의 특징입니다.

 

여기서 cursor의 위치가 요소와 요소 사이에 있다는 것을 출력을 통해 확인해볼 수 있습니다. 

13줄) next() 함수를 호출하면 결과는 1입니다. cursor는 1과 2 사이에 있으며 왼쪽 요소(1)를 반환합니다.

14줄) next() 함수를 한번 더 호출하면 결과가 2입니다. cursor는 2와 3 사이에 있으며 왼쪽 요소(2)를 반환합니다.

 

여기까지 코드를 실행하면 현재 cursor의 위치는 2와 3사이 입니다.

이제 15줄) previous() 함수를 호출하면 cursor가 왼쪽으로 이동하며 cursor의 위치는 1과 2 사이가 됩니다.

대신 반환 요소를 현재 위치에서 오른쪽의 있는 요소(2)를 반환합니다.

이렇듯 커서는 요소와 요소 사이에 있으며, cursor가 이동한 후, 지나온 요소를 반환한다고 생각하시면 됩니다.

 

결과

 

반응형

+ Recent posts