객체 지향 프로그래밍에서 반복자를 사용하여 컨테이너를 가로지르며 컨테이너의 요소들에 접근하는 디자인 패턴.
반복자 패턴은 컨테이너로부터 알고리즘을 분리시키고, 일부의 경우 알고리즘들은 필수적으로 컨테이너에 특화되어있어서 분리가 불가능.유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하기 위해 반복되는 디자인 문제를 해결하는 방법
출처: 위키
컬렉션의 구현 방법을 노출시키지 않으면서 그 집합체 안의 모든 항목에 접근하며 각각에 대한 반복작업을 할 수 있게 해줌
책꽃이 안에 책 꽂은 후, 하나씩 확인하기
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public interface Aggregate {
public abstract Iterator createIterator();
}
public class BookShelf implements Aggregate {
private Book[] books; // 책의 집합
private int last = 0; // 마지막 책이 꽂힌 위치
public BookShelf(int size) {
books = new Book[size];
}
public Book getBook(int index) {
return books[index];
}
public int getLength() {
return last;
}
// 책꽂이에 책을 꽂는다
public void appendBook(Book book) {
if (last < books.length) {
this.books[last] = book;
last++;
} else {
System.out.println("책꽂이가 꽉 찼습니다!");
}
}
@Override
public Iterator createIterator() {
return new BookShelfIterator(this);
}
}
public class BookShelfIterator implements Iterator<Book> {
private BookShelf bookShelf; // 검색을 수행할 책꽂이
private int index = 0; // 현재 처리할 책의 위치
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return index < bookShelf.getLength();
}
@Override
public Book next() {
Book book = bookShelf.getBook(index);
index++;
return book;
}
}
next()는 다음 요소를 반환
hashNext()는 검색을 계속 수행할지 여부를 판단
Main.class
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(10);
Book book1 = new Book("문학동네");
Book book2 = new Book("너무 한낮의 연애");
Book book3 = new Book("늑대의 문장");
bookShelf.appendBook(book1);
bookShelf.appendBook(book2);
bookShelf.appendBook(book3);
System.out.println("현재 꽂혀있는 책 : " + bookShelf.getLength() + "권");
Iterator it = bookShelf.createIterator();
while (it.hasNext()) {
Book book = (Book) it.next();
System.out.println(book.getName());
}
}
>>>현재 꽂혀있는 책 : 3권
>>>문학동네
>>>너무 한낮의 연애
>>>늑대의 문장
iterable: Collection의 상위 인터페이스
public interface Collection<E> extends Iterable<E> {
// ...
}
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Obejcts.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
// ...
}
Iterable 인터페이스 안에 디폴트로 forEach()가 추가 (Java 8 이상)
// forEach()추가 전, stream으로 forEach
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
list.stream().forEach(System.out::println);
// 추가 후, stream생성 필요없이 List에서 바로 forEach 사용 가능
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
list.forEach(System.out::println);
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw ...
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}