본문으로 바로가기

[Java] 자바 8 Iterable API (forEach, spliterator)

category Backend/Java 2021. 12. 19. 00:34

Iterable API

  • 인터페이스의 Default Method 등장으로 인해 Iterable API에 forEach와 spliterator가 추가되었습니다.
public interface Iterable<T> {
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}
  • 아래의 ArrayList를 예시로 사용합니다.
List<String> stockList = new ArrayList<>();
stockList.add("AMZN");
stockList.add("MSFT");
stockList.add("AAPL");
stockList.add("GOOGL");

forEach()

  • 자바의 Collection API인 List, Set, Queue를 람다를 활용해 쉽게 탐색할 수 있습니다.

 

1. 자바 8 이전

[Iterator]

// Iterator 사용
Iterator<String> list = stockList.iterator();
while (list.hasNext()) {
    String stock = list.next();
    System.out.println(stock);
}

[foreach]

// foreach 사용
for(String n : stockList) {
    System.out.println(n);
}

 

2. 자바 8 foreach()

  • default void forEach(Consumer<? super T> action)
  • forEach를 보면 함수형 인터페이스를 매개로 받는 것을 확인 할 수 있습니다. 따라서 람다 표현식을 활용할 수 있습니다.
  • 람다표현식은 반환 값으로 함수형 인터페이스를 반환합니다.
  • Consumer<T> : T 타입을 받아서 아무값도 리턴하지 않는 함수 인터페이스
System.out.println("--- forEach 익명 클래스  ---");
stockList.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        System.out.println(s);
    }
});

System.out.println("--- forEach 람다 ---");
stockList.forEach(s -> System.out.println(s));

System.out.println("--- forEach 메소드 레퍼런스 ---");
stockList.forEach(System.out::println);

spliterator()

  • iterator가 반복이라면 spliterator는 분할 할 수 있는 반복입니다.
  • 병렬 작업에 유리하게 사용할 수 있습니다.
public interface Spliterator<T> {
    // 탐색 여부 반환
    boolean tryAdvance(Consumer<? super T> action);

    // 모든 요소가 처리되거나 예외 throw 될 때 까지 지정 작업 수행
    default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }
    
    // Spliterator 일부 요소를 분할해서 새로운 Spliterator 생성
    Spliterator<T> trySplit();
    
    // 남은 요소 개수
    long estimateSize();
    
    // ( . . . ) 생략
}

 

1. 자바 8 spliterator()

[탐색]

Spliterator<String> spliterator1 = stockList.spliterator();
while(spliterator1.tryAdvance(System.out::println));

Spliterator<String> spliterator2 = stockList.spliterator();
spliterator2.forEachRemaining(System.out::println);

 

[분할 탐색]

Spliterator<String> spliterator1 = stockList.spliterator();
Spliterator<String> spliterator2 = spliterator1.trySplit();

System.out.println("=========");
spliterator1.forEachRemaining(System.out::println); // AAPL, GOOGL
System.out.println("=========");
spliterator2.forEachRemaining(System.out::println); // AMZN, MSFT
System.out.println("=========");