Iterator
컬렉션 프레임웍에서는 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화하였다. 컬렛션에 저장된 각 요소에 접근하는 기능을 가진 Iterator 인터페이스를 정의하고 Collection인터페이스에 Iterator(Iterator를 구현한 클래스의 인스턴스)를 반환하는 iterator()를 정의하고있따
public interface Iterator{
boolean hasNext();
Object next();
void remove();
}
public interface Collection{
...
public Iterator iterator();
....
}
iterator()는 Collection인터페이스에 정의된 메서드이므로 Collection인터페이스의 자손인 List와 Set에도 포함되어 있다. 그래서 List나 Set인터페이스를 구현하는 컬렉션은 iterator()가 각 컬렉션의 특징에 알맞게 작성되어 있다, 컬렉션 클래스에 대해 iterator()를 호출하여 Iterator를 얻은 다음 반복문을 사용해서 컬렉션클래스의 요소들을 읽어 올 수 있다.
boolean hasNext() -> 읽어 올 요소가 남아있는지 확인한다 있으면 true 없으면 false를 반환한다
Object next() -> 다음 요소를 읽어 온다 . next()를 호출하기 전에 hasNext()를 호출해서 읽어 올 요소가 있는지 확인하는 것이 안전하다.
void remove() -> next()로 읽어 온 요소를 삭제한다 . next()를 호출한 다음에 remove()를 호출해야한다 (선택적 기능)
ArrayList에 저장된 요소들을 출력하기 위한 코드는 다음과 같이 작성할 수 있다.
List list = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
ArrayList대신 List인터페이스를 구현한 다른 컬렉션 클래스에 대해서도 이와 동인한 코드를 사영할 수 있다 . 첫 줄에서 ArrayList대신 List인터페이스를 구현한 다른 컬렉션 클래스의 객체를 생성하도록 변경하기만 하면 된다.
Iterator를 이용해서 컬렉션의 요소를 읽어오는 방법을 표준준화했기 떄문에 이처럼 코드의 재사용성을 높이는 것이 가능한 것이다
이처럼 공통 인터페이스를 정의해서 표준을 정의하고 구현하여 표준을 따르도록 함으로써 코드의 일관성을 유지하여 재사용성을 극대화하는 것이 객체지향프로그래밍의 중요한 목적 중의 하나이다
Map인터페이스를 구현한 컬렉션 클래스는 키와 값을 쌍으로 저장하고 있기 떄문에 iterator()를 직접 호출할 수 없고 그 대신 keyset이나 entrySet()과 같은 메서드를 통해서 키와 값을 각각 따로 Set의 형태로 얻어 온 후에 다시 iterator()를 호출해야 Iterator를 얻을 수 있다.
Map map = new HashMap();
....
Iterator it = map.keySet().iterator();
Iterator list = map.entrySet();
Iterator list = eSet.iterator();
이 문장들의 실행순서를 그림으로 그려보면 다음과 같다.
Iterator list = map.entrySet().itreator();
1. map.entrySet()실행결과가 Set이므로
-> Iterator list = map.entrySet().iterator(); -> Iterator list = Set인스턴스.iterator();
2. map.entrySet()를 통해 얻은 Set인스턴스의 iterator(); Iterator list = iterator인스턴스;
3. 마지막으로 iterator 인스턴스의 참조가 list에 저장된다.
StringBuffer를 사용할떄 이와 유사한 코드를 많이 보았을 것이다.
StringBuffer sb = new Stringbuffer();
sb.append("a");
sb.append("b");
sb.append("c");
위와 같은 코드를 아래와 같이 간단히 쓸 수 있는데 그 이유는 바로 append메소드가 수행결과로 StringBuffer를 리턴하기 떄문이다.
만일 void append(String str)와 같이 void 를 리턴하도록 선언되어 있다면 위의 코드를 아래와 같이 쓸 수 없다. append메소드의 호출결과가 void이기 떄문에 또 다시 void 에 append메서드를 호출 할 수 없기 떄문이다.
StringBuffer sb = new StringBuffer();
sb.append("a").append("b").append("c"); // StringBuffer append(String str)
List 클래스들은 저장순서를 유지하기 떄문에 Iterator를 이용해서 읽어 온 결과 역시 저장 순서와 동일 하지만 Set클래스들은 각 요소간의 순서가 유지 되지 않기 떄문에 Iterator 를 이용해서 저장된 요소들을 읽어 와도 처음에 저장된 순서와 같지않다.
요약 ->
Iterator 는 인터페이스 -> Collection인터페이스에 정의됨 -> List , set 에서 재정의하여 각자에맞게 사용-> Collection 객체 요소들을 읽어올떄 사용한다
iterator() 재귀호출을사용함
iterator 인터페이스선언을통해 iterator 표준화를 할수잇으며 이를통해 코드의 재사용성을높이고 일관성을유지하여 객체지향프로그래밍을 효율을 극대화 할수있다.