Programming/Java

Java Iterable Iterator 차이점 정리

Jan92 2022. 12. 2. 01:18
반응형

지금까지 java를 배우고 실무에 활용하면서 Iterator, Iterable을 직접적으로 쓴 적은 한 번도 없었는데요.

최근 다른 코드에서 해당 인터페이스들을 사용하는 것을 보고 무슨 기능을 하는지 궁금해서 정리한 내용입니다.

 

Iterator

출처: https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html

Iterator는 Java Collections Framework에 속해있으며, java 1.2에서 발표된 인터페이스입니다.

Iterator는 Collection에 저장된 요소를 읽어오는 것을 표준화한 인터페이스로 데이터를 하나씩 읽어올 때 사용되는데요.

 

다음 요소를 가지고 있으면 true를 반환하는 hasNext() 메서드와 다음 요소를 반환하는 next() 메서드가 있으며, default 메서드로 해당 iterator로 반환된 요소를 제거하는 remove() 메서드, 모든 요소가 처리되거나 예외가 throw 될 때까지 각 나머지 요소에 대해 지정된 작업을 수행하는 forEachRemaining() 메서드가 있습니다.

 

 

 

Iterable

출처: https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html

Iterable 인터페이스는 Iterator가 나온 이후인 java 1.5부터 나왔는데요. java.lang 패키지에 속하며, 반복할 수 있는 데이터 구조를 나타냅니다.

(java의 모든 Collection은 Iterable 인터페이스를 상속받아 Iterable의 메서드를 구현합니다.)

Iterable 인터페이스에는 Iterator 구현체를 반환하는 iterator() 메서드가 선언되어 있는데요. 따라서 해당 인터페이스를 상속받은 하위 클래스들은 iterator() 메서드를 구현해야 하고, 해당 메서드의 구현을 통해 iterator를 사용할 수 있습니다.

 

또한 이 인터페이스는 for-each loop를 사용할 수 있는 클래스라는 것을 명시해주는 기능도 제공하는데요. Iterable을 상속받는 클래스는 Iterator를 사용하여 for-each loop를 사용할 수 있게 됩니다.

 

 

//일반적인 for문
for (int i=0; i<length; i++) {
    …
}

//for each문
for (String str : list) {
    System.out.println(str);
}

//for each문이 실제 동작되는 코드 (iterator가 사용됨)
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    System.out.println(iterator.next());
}

향상된 for문(The enhanced for statement)이라고 불리는 for-each loop는 일반 for loop처럼 for 키워드로 시작합니다.

루프 카운터 변수를 선언하고 초기화하는 대신, 배열의 기본 유형과 동일한 유형인 변수를 선언하고 그 뒤에 콜론과 루프를 돌릴 배열을 차례로 선언하는데요. 루프 본문에서는 인덱스 배열 요소를 사용하는 대신 생성된 루프 변수를 사용할 수 있게 됩니다.

(배열 또는 컬렉션 클래스를 반복하는데만 사용할 수 있습니다.)

 

* java 1.8부터는 Iterable에 forEach default 메서드를 제공하고 있습니다.

 

 

 

인터페이스 계층 구조 및 ArrayList 예시

Iterable 하위 인터페이스 계층 구조

Collection 인터페이스와 List, Set, Queue 인터페이스의 계층 구조를 통해 Iterable과 Iterator에 대해서 조금 더 살펴보겠습니다.

 

Iterable은 Collection의 상위 인터페이스인데요. 위에서 본 것처럼 Iterable 인터페이스에는 iterator() 메서드가 선언되어 있습니다.

때문에 Collection 인터페이스 계층구조에서 List, Set, Queue를 구현하는 클래스들은 다 iterator() 메서드를 가지고 있게 되는데요.

결론적으로 Iterable의 역할은 iterator() 메서드를 하위 클래스에서 무조건 구현하게 만들기 위함이라고 볼 수 있습니다.

 

(그리고 그 하위 클래스에서는 iterator() 메서드를 구현하여 반환된 Iterator 구현체를 통해 반복 동작을 사용할 수 있게 됩니다.)

 

 

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
 
    ...
     
    public Iterator<E> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        ...

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            ...
        }
        
        ...
    }  
     ...
}

(ArrayList를 통한 예시)

 

  1. Iterable 인터페이스는 하위 클래스가 추상 메서드 'iterator()'를 구현하도록 합니다.
  2. Iterator 인터페이스는 하위 클래스가 추상 메서드 'hasNext()' 'next()'를 구현하도록 합니다.
  3. ArrayList는 List를 구현하고 List는 Collection을 상속받고 Collection은 Iterable을 상속받습니다.

    즉, 다음과 같은 관계를 볼 수 있는데요.
    Iterable  <-  Collection  <- List  <-  ArrayList

    실질적으로 Iterable, Collection, List는 'iterator()' 메서드를 선언만 하고 ArrayList에서 해당 메서드가 실제로 구현됩니다.

  4. 그리고 위 코드 예시는 ArrayList에서 iterator() 메서드를 구현하는 부분에 대한 자세한 코드인데요.
    'iterator()' 메서드는 Iterator를 구현한 'Itr' 클래스의 객체를 반환합니다.
    (Itr 클래스 내부에 hasNext(), next() 메서드가 구현된 것도 볼 수 있습니다.)

 

 

정리하자면

Iterable 인터페이스는 하위 클래스에서 iterator()의 생성을 강제하는 역할을 하게 되는데요.

따라서 Iterable을 상속받은 Collection의 하위 클래스들은 모두 iterator() 메서드를 가지고 있게 되며, Iterator 인터페이스를 구현한 클래스는 hasNext(), next() 등을 구현하고 있기 때문에 이를 활용하여 반복 기능을 사용할 수 있게 되는 것입니다.

 

 

 

< 참고 자료 >

https://girawhale.tistory.com/17

https://wedul.site/459

https://stackoverflow.com/questions/6863182/what-is-the-difference-between-iterator-and-iterable-and-how-to-use-them

반응형