본문

Iterator와 ListIterator(JAVA)

반응형

# Iterator

컬렉션 프레임웍에서는 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화하였다. 컬렉션에 저장된 각 요소에 접근하는 기능을 가진 Iterator인터페이스를 정의하고, Collection인터페이스인 Iterator(Iterator를 구현한 인스턴스)를 반환하는 iterator()를 정의하고 있다.


 메서드

설명 

boolean hasNext() 

읽어 올 요소가 있는지 확인한다. 있으면 true,
없으면 false를 반환한다. 

Object next() 

다음 요소를 읽어 온다.
next()를 호출하기 전에 hasNext()를 호출해서
읽어 올 요소가 있는지 확인하는 것이 안전하다. 

void remove() 

next()로 읽어 온 요소를 삭제한다.
next()를 호출한 다음에 remove()를 호출해야한다.(선택적 기능) 


ArrayList에 저장된 요소들을 출력하기 위한 코드는 다음과 같이 작성할 수 있다.

1
2
3
4
5
6
7
List list = new ArrayList();        // 다른 컬렉션으로 변경할 때는 이 부분만 고치면 된다.
 
Iterator it = list.iterator();
 
while(it.hasNext()) {
    System.out.println(it.next());
}
cs


Iterator를 이용해서 컬렉션의 요소를 읽어오는 방법을 표준화했기 때문에 이처럼 코드의 재사용성을 높이는 것이 가능한 것이다.

이처럼 공통 인터페이스를 정의해서 표준을 정의하고 구현하여 표준을 따르도록 함으로써 코드의 일관성을 유지하여 재사용성을 극대화하는 것이 객체지향 프로그래밍의 중요한 목적 중 하나이다.



Map인터페이스를 구현한 컬렉션 클래스는 키(keey)와 값(value)을 쌍으로 저장하고있기 때문에 iterator()를 직접 호출할 수 없고
그 대신 keySet()이나 entrySet()과 같은 메서드를 통해서 키와 값을 각각 따로 Set의 형태로 얻어 온 후에 다시 iterator()를 호출해야 Iterator을 얻을 수 있다.


1
2
3
Map mep = new HashMap();
...
Iterator it = map.keySet().iterator();
cs

Iterator list = map.entrySet().iterator(); 는 아래의 두 문장을 하나로 합친 것이라고 이해하면 된다.

1
2
Set eSet = map.entrySet();
Iterator list = eSet.iterator();
cs


StringBuffer를 사용할 때 이와 유사한 코드를 많이 보았을 것이다.

1
2
3
4
StringBuffer sb = new StringBuffer();
sb.append("A");
sb.append("B");
sb.append("C");
cs


위와 같은 코드를 아래와 같이 간단히 쓸 수 있는데, 그 이유는 바로 append메서드가 수행결과로 StringBuffer를 리턴하기 때문이다.

만일 void append(String str)와 같이 void를 리턴하도록 선언되어 있다면 위의 코드를 아래와 같이 쓸 수 없다. 

append메서드의 호출결과가 void이기 때문에 또 다시 void에 append메서드를 호출 할 수 없기 때문이다.


1
2
StringBuffer sb = new StringBuffer();
sb.append("A").append("B").append("C");        
cs


Source 01) IteratorEx01.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package IteratorEx;
 
import java.util.ArrayList;
import java.util.Iterator;
 
public class IteratorEx01 {
 
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
 
        for (int i = 1; i <= 5; i++) {
            list.add(i);
        }
 
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}
cs

Result)

1
2
3
4
5
1
2
3
4
5
cs

List클래스들은 저장순서를 유지하기 때문에 Iterator를 이용해서 읽어 온 결과 역시 저장순서와 동일하지만,

Set클래스들은 각 요소간의 순서가 유지되지 않기 때문에 Iterator를 이용해서 저장된 요소들을 읽어 와도 처음에 저장된 순서와 같지 않다.


아웃룩 예제

마이크로소프트 아웃룩(Microsoft outlook)과 같은 email클라이언트에서 메일서버에 있는 메일을 가져올 때 서버에 있는 메일을 읽어만 올 것인지(copy), 메일을 가져오면서 서버에서 삭제할 것(move)인지를 선택할 수 있다. 이와 같은 기능을 구현하고자 할 때 쓸 목적으로 remove()를 정의해 놓은 것이다. 단순히 서버에서 읽어오기만 할 때는 next()를 사용하면 되고, 읽어 온 메일을 서버에 남기지 않고 지울 때는 next()와 함께 remove()를 사용하면 이와 같은 기능을 구현할 수 있다.


Source 02) IteratorEx02.java

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
32
33
34
35
36
37
38
39
40
41
42
43
package IteratorEx;
 
import java.util.ArrayList;
import java.util.Iterator;
 
public class IteratorEx02 {
    static final int SIZE = 10;
 
    public static void main(String[] args) {
        ArrayList original = new ArrayList(SIZE);
        ArrayList copy1 = new ArrayList(SIZE);
        ArrayList copy2 = new ArrayList(SIZE);
 
        for (int i = 0; i < SIZE; i++) {
            original.add(i + "");
        }
 
        Iterator it = original.iterator();
 
        while (it.hasNext()) {
            copy1.add(it.next());
        }
 
        System.out.println("= Original에서 copy1로 복사(copy) =");
        System.out.println("original : " + original);
        System.out.println("copy1 : " + copy1);
        System.out.println();
 
        // Iterator은 재사용이 안되므로, 다시 얻어와야한다.
        it = original.iterator();
 
        while (it.hasNext()) {
            copy2.add(it.next());
            it.remove();
        }
 
        System.out.println("= Original에서 copy2로 이동(move) =");
        System.out.println("original : " + original);
        System.out.println("copy2 : " + copy2);
        System.out.println();
 
    }
}
cs

Result)

1
2
3
4
5
6
7
= Original에서 copy1로 복사(copy) =
original : [0123456789]
copy1 : [0123456789]
 
= Original에서 copy2로 이동(move) =
original : []
copy2 : [0123456789]
cs

# ListIterator

ListIterator는 Iterator를 상속받아서 기능을 추가한 것으로, 컬렉션의 요소에 접근할 때 Iterator는 단방향으로만 이동할 수 있는 데 반해 ListIterator는 양방향으로의 이동이 가능하다. 다만 ArrayList나 LinkedList와 같이 List인터페이스를 구현한 컬렉션에서만 사용할 수 있다.


Source 01) ListIteratorEx0.java

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
package IteratorEx;
 
import java.util.ArrayList;
import java.util.ListIterator;
 
public class ListIteratorEx01 {
    static final int MAX_SIZE = 5;
 
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
 
        for (int i = 1; i <= MAX_SIZE; i++) {
            list.add(i);
        }
 
        ListIterator it = list.listIterator();
 
        while (it.hasNext()) {
            // 순방향으로 진행하면서 읽어온다.
            System.out.print(it.next());
        }
 
        System.out.println();
 
        while (it.hasPrevious()) {
            // 역방향으로 진행하면서 읽어온다.
            System.out.print(it.previous());
        }
    }
}
cs

Result)

1
2
12345
54321
cs




출처 및 참고자료 : JAVA의정석(남궁성 저)

반응형

공유

댓글