1일1배움/Java

[23/07/17] Iterable, Iterator

kim chan jin 2023. 7. 17. 12:14

Iterable

- 컬렉션을 순회할 수 있는 객체를 나타내는 인터페이스

- Iterable 인터페이스를 상속받은 컬렉션 클래스는 forEach() 사용가능

- iterator() 메서드: Iterable 컬렉션의 요소에 접근하기 위한 인터페이스 참조타입 객체를 반환 ( 하지만 실제로 컬렉션 구현체 클래스에서  Iterable 인터페이스를 상속받지 않은 채로 직접 iterator를 오버라이딩한다. 왜냐하면 Iterable 인터페이스가 도입되기 전부터 존재했던 컬렉션 클래스들과의 호환을 위해서이다.

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

public interface Iterable<T> {
    
    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) { // 와일드카드, super로 다형성 꾀함
        Objects.requireNonNull(action);
        for (T t : this) { // this: Iterable 인터페이스를 상속받은 컬렉션 클래스(조상 클래스 포함)를 의미
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

 

 

Iterator

- Iterable 컬렉션의 요소에 접근하기 위한 인터페이스

- hasNext(), next(), remove() 메서드가 선언되어 있다.

- 각 컬렉션의 내부클래스에서 Iterator 인터페이스를 상속받고 해당 컬렉션의 성격에 알맞게 구현되어 있다.

package java.util;

import java.util.function.Consumer;

public interface Iterator<E> {
    
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

 

 

실제 ArrayList 코드 일부분

public class ArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

    // ...

    public Iterator<E> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        // prevent creating a synthetic constructor
        Itr() {}

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

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
        
    // ...
}