[JAVA]디자인패턴-1.Iterator

iterator 패턴은

자바 프로그래밍을 하다 보면 Array, Set, Map, List 과 같은 자료구조를 많이 사용하게 된다.
이 자료구조의 특징들은 어떠한 데이터들의 집합체라는 것이다. 그래서 집합체들을 다룰 때는 얘들이 가지고 있는 개별 원소에 대해서 이런 저런 작업들을 할 일이 많다.
iterator를 쓰게 되면, 집합체와 개별 원소들간에 분리시켜 생각할 수가 있다.
심지어는 그 집합체가 어떤 클래스의 인스턴스인지 조차 신경쓰지 않아도 된다.

예제

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
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MagicianList implements Iterable<String> {
private List<String> list = new ArrayList<String>();

public void add(String name){
list.add(name);
}

public Iterator<String> iterator() {
return new Iterator<String>(){
int seq = 0;
public boolean hasNext() {
return seq < list.size();
}
public String next() {
return list.get(seq++);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}


public static void main(String[] arg){
MagicianList magicians = new MagicianList();
magicians.add("이은결");
magicians.add("Kevin parker");
magicians.add("David Blaine");

Iterator<String> iterator = magicians.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
}
}

magicians 의 원소들을 뽑아내는데, magicians 라는 변수를 전혀 쓰지 않는다.
물론, 내부적으로 iterator라는 변수가 magicians와 관계를 유지해주고 있긴 하지만 일단 iterator를 가지고 온 후에는 데이터 집합체가 뭐냐에 신경을 쓸 필요가 없어진 것이다.
iterator만 가져오면, hasNext() , next() 만 가지고 반복하면서 원소들에 대해서 처리를 하면 된다.

Iterator관련 interface

Iteraable 인터페이스를 보게되면 Iterator iterator() 라는 메소드 한개만 가지고 있다.
그리고 이 iterator 메소드를 이용하여 만들어진 iterator클래스는 클래스는 3개의 메서드를 가지고 있다.
hasNext()는 다음 구성 요소가 있냐고 물어보는 메서드이다. next()는 그 요소를 뽑아 온다.
remove()는 일부러 구현을 안하였다.
API에 보면, 마지막으로 꺼낸 요소를 제거한다.(optional operation) 이라고 되어있는데 optional이라는 걸 강조하기위해 구현을 하지 않았다.
요기서 한가지 짚고 넘어가야 할 것은 시퀀스는 hasNext()가 아니라 next()에서 증가시켜야 한다는 것이다.
hasNext()를 호출하고 또 호출하는 일이 발생할 수도 있기 때문이다. hasNext라는 메소드 이름이, next를 가지고 있는지를 체크하겠다는 것이기 때문이다.

JAVA API에 있는 Iterator

우리가 알고 있는 일반적인 집합체들은 전부 Iterator를 제공한다.
Set, List 등은 Collection 을 상속 받는데, Collection이 Iteratable을 상속 받기 때문이다.
위에서 만든 클래스처럼 리스트같은 Collection을 사용할땐 list.iterator()를 사용하여 각 컬렉션의 iterator를 뽑아올 수 있다.

Map은 왜 Iterator를 제공하지 않는 지를 살펴보자.
Map은 Set이나 List와는 달리 key-value의 구조이다. key에 대한 Iterator인지 value에 대한 Iterator인지 구별할 방법이 없다. 그래서 아예 제공을 하지 않는다.
그러나 Map에는 key에 대해서는 Set keySet()이라는 key를 Set으로 가져오기를 지원하고, value에 대해서는 Collection values() 를 제공한다. 위에서 말한것 처럼 Set과 Collection은 둘다 Iterator를 제공한다.