[java] Java 8 JDK를 사용하여 Iterable을 스트림으로 변환

을 반환하는 인터페이스가 java.lang.Iterable<T>있습니다.

Java 8 Stream API를 사용하여 그 결과를 조작하고 싶습니다.

그러나 Iterable은 “스트리밍”할 수 없습니다.

Iterable을 List로 변환하지 않고 Stream으로 사용하는 방법에 대한 아이디어가 있습니까?



답변

spliteratorUnknownSize직접 사용하는 것보다 훨씬 더 나은 대답이 있습니다. 더 쉽고 더 나은 결과를 얻을 수 있습니다. Iterablespliterator()당신이 당신 spliterator를 얻기 위해 그것을 사용한다, 그래서 방법을. 최악의 경우 동일한 코드 (기본 구현은 spliteratorUnknownSize)를 사용 하지만 더 일반적인 경우에는 Iterable이미 모음 인 경우 더 나은 스플리터를 얻을 수 있으므로 스트림 성능이 향상됩니다 (병렬 처리도 가능). 또한 코드가 적습니다.

StreamSupport.stream(iterable.spliterator(), false)
             .filter(...)
             .moreStreamOps(...);

보시다시피, 스트림에서 스트림을 얻는 것은 Iterable( 이 질문 도 참조하십시오 ) 고통스럽지 않습니다.


답변

버전 21부터 Guava 라이브러리를 사용할 수있는 경우

Streams.stream(iterable)


답변

당신은 쉽게 만들 수 있습니다 StreamIterable또는 Iterator:

public static <T> Stream<T> stream(Iterable<T> iterable) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            iterable.iterator(),
            Spliterator.ORDERED
        ),
        false
    );
}


답변

JOOL 라이브러리 사용을 제안 하고 싶습니다 .Seq.seq (iterable) 호출 뒤에 spliterator 마술을 숨기고 유용한 기능을 추가로 제공합니다.


답변

따라서 다른 답변으로 구아바는 다음을 사용하여이를 지원합니다.

Streams.stream(iterable);

구현이 제안 된 다른 답변과 약간 다른 점을 강조하고 싶습니다. (가) 경우 Iterable유형 인 Collection그들은 그것을 캐스팅.

public static <T> Stream<T> stream(Iterable<T> iterable) {
  return (iterable instanceof Collection)
    ? ((Collection<T>) iterable).stream()
    : StreamSupport.stream(iterable.spliterator(), false);
}

public static <T> Stream<T> stream(Iterator<T> iterator) {
  return StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(iterator, 0),
    false
  );
}


답변

이 클래스를 만들었습니다.

public class Streams {
    /**
     * Converts Iterable to stream
     */
    public static <T> Stream<T>  streamOf(final Iterable<T> iterable) {
        return toStream(iterable, false);
    }

    /**
     * Converts Iterable to parallel stream
     */
    public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) {
        return toStream(iterable, true);
    }

    private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) {
        return StreamSupport.stream(iterable.spliterator(), isParallel);
    }
}

스플리터와 부울 (isParallel)에 대해 생각할 필요가 없기 때문에 완벽하게 읽을 수 있다고 생각합니다.


답변

이 문제에 대한 매우 간단한 해결 방법 은 메소드 를 보유하는 Streamable<T>인터페이스 확장 을 작성 Iterable<T>하는 default <T> stream()것입니다.

interface Streamable<T> extends Iterable<T> {
    default Stream<T> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

이제 대신을 ( Iterable<T>를) 선언하여 간단하게 스트리밍 할 수 있습니다 .implements Streamable<T>Iterable<T>