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


418

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

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

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

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


2
반복 할 수 있다면 루프를 사용하여 상태 또는 값을 확인하거나 그 밖의 것을 확인하십시오.
Afzaal Ahmad Zeeshan

26
@AfzaalAhmadZeeshan 시냇물이 훨씬 더
좋아서

1
내가 말했듯이, 그 목록에 대한 몇 가지 조작 (필터, 매핑)을 수행해야합니다. 새로운 Java 8 JDK API-> Stream을 사용하고 싶습니다. 그러나 Iterable은 "SteamAble"이 아닙니다
rayman

myIterable.stream()존재하지 않는 이상한 것 같습니다 !
Josh M.

7
@Guillaume : 네,하지만 Stream.of(iterable)생산 Stream<Iterable<Object>>.
Matthias Braun

답변:


571

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

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

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


109
정적 메소드 Stream가 좋았습니다 (예 :) Stream.ofIterable(iterable).
robinst

59
@robinst 이것은 생략이 아니었다; 그것은 고의적 인 (그리고 논쟁의 여지가 많은) 선택이었습니다. 문제는 이것이 존재해야한다는 것인데, 그에 따른 장단점을 이해하지 않고서는 도달하기가 너무 쉽다는 것입니다. Iterable은 매우 추상적이기 때문에 이러한 방법은 가능한 최악의 스트림 (병렬 지원, 크기 정보 또는 특성 없음 (실행 선택을 최적화하는 데 사용))을 초래합니다. 더 많은 사고를 강요하면 전체 생태계에서 더 나은 API를 얻게됩니다. 이것은 "XYZ 코드에 가장 적합한 것"과 "모든 Java 코드에 가장 좋은 것"의 균형이었습니다.
Brian Goetz

2
귀하의 설명에 따라 왜 우리가 Collection.stream ()을 얻었지만 Iterable.stream ()을 얻지 못한 지 궁금합니다. Iterable.stream () (또는 Stream.ofIterable ())을 생략하는 이유는 Collection.stream ()에 동일하게 적용됩니다.
qualidafial

6
@qualidafial stackoverflow.com/questions/23114015/…를 참조하십시오 .
Brian Goetz

11
@BrianGoetz 대부분의 사람들이 당신이 위에서 말했거나 신경 쓰지 않는 것을 이해하는 수준에 있지 않은 것 같습니다. 간단한 API를 호출하여 간단한 코드 만 작성하려고합니다. 반면에, 그 것들 (병렬 ...)은 대부분의 일상 반복 작업에 중요하지 않을 수 있습니다.
user_3380739


23

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

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

2
이 함수를 한 번 작성한 다음 호출하면됩니다. 왜 stream(...)코드 호출이 복잡합니까?
gexicide

1
인라인 짧고 우아합니다. 바로이 함수를 한 번 작성할 수 있습니다. 그러나 코드를 삭제하지 않고 코드를 추가하지 않습니다. 어쨌든이 대답은 옳습니다. 그것이 이것을 변환하는 방법이기 때문입니다.
rayman

정적 가져 오기 기능을했다. 짧고 우아합니다. (반드시 투명 아니지만)
aepurniet

9

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


7

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

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
  );
}

5

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

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)에 대해 생각할 필요가 없기 때문에 완벽하게 읽을 수 있다고 생각합니다.


4

이 문제에 대한 매우 간단한 해결 방법 은 메소드 를 보유하는 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>


0

Vavr (이전의 Javaslang)을 사용하는 경우 다음과 같이 쉽습니다.

Iterable i = //...
Stream.ofAll(i);

-1

Java 8과 외부 라이브러리가없는 다른 방법 :

Stream.concat(collectionA.stream(), collectionB.stream())
      .collect(Collectors.toList())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.