Enumeration VS Iterator

콜렉션 프레임워크의 클래스들은 객체를 저장하고 정리하기 위해 사용된다. 
콜렉션 클래스들 내에 저장된 객체들을 차례로 접근하기 위한 방법을 콜렉션 뷰라고 한다.
 자바 2 이전 버전에서 사용되던 Vector, Hashtable의 뷰 객체는 Enumeration 객체이며, 
자바 2의 콜렉션 프레임워크에서 콜렉션 뷰는 Iterator와 ListIterator 객체이다.
 

Vector 클래스의 객체인 v 객체의 모든 요소(저장된 객체)들을 Enumeration 뷰를 이용하여 프린트하려면 다음과 같다.

for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {
    System.out.println(e.nextElement());
}

같은 Vector 클래스의 객체 v 객체를 Iterator 뷰를 이용하여 모든 요소를 프린트하려면 다음과 같다.

for (Iterator it = v.iterator() ; it.hasNext() ;) {
    System.out.println(it.next());
}

Iterator 객체가 Enumeration 객체와 다른 점은 Iterator 객체는 콜렉션에 대하여 remove() 메소드를 제공한다는 점이다.
 또한 메소드의 이름이 훨씬 명시적이다. 
그리고, 자바 2 버전에서는 Enumeration 보다는 잘 정의된 콜렉션 뷰 객체인 Iterator를 사용할 것을 권하고 있다.


Fail-fast

그러나, Enumeration 객체와 Iterator 객체의 뷰 방식에는 또 다른 차이점이 있다. 
자바 2 이전 버전에서 사용되던 Vector, Hashtable의 뷰 객체인 Enumeration은 fail-fast 방식이 아니었으나, 
자바 2의 콜렉션 프레임워크에서 콜렉션 뷰인 Iterator, ListIterator 객체는 fail-fast 방식이라는 점이다.

콜렉션 뷰는 콜렉션 객체에 저장된 객체들에 대한 순차적 접근을 제공한다. 그러나,
 뷰 객체인 Enumeration 또는 Iterator 객체를 얻고 나서 순차적 접근이 끝나기 전에 뷰 객체를 얻은 하부
 콜렉션 객체에 변경이 일어날 경우, 순차적 접근에 실패하게 된다.
 여기서 변경이라는 것은 콜렉션에 객체가 추가되거나 제거되는 것과 같이 콜렉션 구조의 변경이 일어나는 경우를 말한다.

이런 상황은 멀티쓰레드 구조와 이벤트 구동 모델에서 일어날 수 있으며, 
개발자가 혼자 테스트할 경우 발견하기 어려운 문제이다. 따라서 정확한 이해와 예상이 필요하며,
 이에 대한 대처 방안을 마련해야 한다.

하부 콜렉션 객체에 변경이 일어나 순차적 접근에 실패하면 Enumeration 객체는 실패를 무시하고 
순차적 접근을 끝까지 제공한다. Iterator 객체는 하부 콜렉션 객체에 변경이 일어나 순차적 접근에 실패하면 ConcurrentModificationException 예외를 발생한다. 
이처럼 순차적 접근에 실패하면 예외를 발생하도록 되어 있는 방식을 fail-fast라고 한다.

Iterator는 fail-fast 방식으로 하부 콜렉션에 변경이 발생했을 경우, 신속하고 결함이 
없는 상태를 만들기 위해 Iterator의 탐색을 실패한 것으로 하여 예외를 발생하며,
 이렇게 함으로써 안전하지 않을지도 모르는 행위를 수행하는 위험을 막는다.

왜냐하면 이러한 위험은 실행 중 불특정한 시간에 멋대로 결정되지 않은 행위를 할 가능성이 있기 
때문에 안전하지 않다고 할 수 있기 때문이다.


출처 - http://darkmirr.egloos.com/1227598











Posted by linuxism

댓글을 달아 주세요