[Java] Iterable과 Iterator
in Java on Java
Last modified at:
이펙티브 자바 3판을 읽다가 Iterable<E>
를 입력 매개변수 타입으로 받는 소스코드 발견했다. Iterator가 반복자인 것만 알고있었는데 Iterable은 뭐지? 이름만 봐서는 인터페이스 같은데… 궁금해서 찾아보게 되었다.
1. Iterable이란?
- Iterable은 Collection의 상위 인터페이스
- Collection은 List, Set, Queue 인터페이스의 상위 인터페이스
내부 구현코드를 확인해보면 Collection 인터페이스의 상위 인터페이스는 Iterable임을 알 수 있다.
/**
* Implementing this interface allows an object to be the target of the enhanced
* {@code for} statement (sometimes called the "for-each loop" statement).
*
* @param <T> the type of elements returned by the iterator
*
* @since 1.5
* @jls 14.14.2 The enhanced {@code for} statement
*/
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
...
}
Iterable의 내부 구현코드를 보면 이 인터페이스 안에는 iterator 메소드가 추상메소드로 선언되어있다. 그러므로 Collection 인터페이스 계층구조에서 List, Set, Queue를 구현하는 클래스들은 다 iterator 메소드를 가지고 있다. 따라서 Iterable의 역할은 iterator() 메소드를 하위 클래스에서 무조건 구현을 하게 만들기 위함이다.
2. Iterator란?
Iterator 인터페이스는 Collection과는 별개로 존재하는 인터페이스이다.
public interface Iterator<E> {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
/**
* Removes from the underlying collection the last element returned
* by this iterator (optional operation). This method can be called
* only once per call to {@link #next}.
* <p>
* The behavior of an iterator is unspecified if the underlying collection
* is modified while the iteration is in progress in any way other than by
* calling this method, unless an overriding class has specified a
* concurrent modification policy.
* <p>
* The behavior of an iterator is unspecified if this method is called
* after a call to the {@link #forEachRemaining forEachRemaining} method.
*
* @implSpec
* The default implementation throws an instance of
* {@link UnsupportedOperationException} and performs no other action.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this iterator
*
* @throws IllegalStateException if the {@code next} method has not
* yet been called, or the {@code remove} method has already
* been called after the last call to the {@code next}
* method
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
...
}
Iterator 인터페이스의 내부 구현은 위와 같이 되어있다. 따라서 hasNext(), next(), remove() 등의 메소드 사용이 가능하다.
- 용도: 컬렉션 클래스의 데이터를 하나씩 읽어올 때 사용
- 표준화가 되어 있지 않다면 컬렉션 클래스의 데이터를 읽어올 때 마다, 해당 클래스의 데이터를 꺼내오는 메서드들을 다 알고 있어야 함. 이름이 다를 수도 있는데 그걸 다 알고 있어야 하는건 비 효율적이다!
- 위와 같은 이유로 인해 Iterator가 존재하는 것
위와같은 Iterator 인터페이스는 객체지향 프로그래밍의 중요한 목적 중의 하나임
객체지향 프로그래밍의 중요한 목적
- 공통 인터페이스를 정의하여 표준을 정의
- 위 인터페이스를 구현하여 표준을 따르도록 하며 코드의 일관성을 유지
- 재사용성을 극대화
public class Test {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("Cho");
list.add("a");
list.add("ra");
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next()+" ");
}
}
}
- 참조변수 list로 iterator 메소드를 호출
- iterator 메소드는 Linkedlist 형태의 Iterator를 반환
- 반환한 Iterator의 hasNext, next 메소드를 통해 내용을 출력함