[java] Stream <T>가 Iterable <T>를 구현하지 않는 이유는 무엇입니까?

Java 8에는 Stream <T> 클래스가 있는데 , 여기에는 흥미롭게 메소드가 있습니다

Iterator<T> iterator()

따라서 Iterable <T> 인터페이스를 구현할 것으로 예상 할 수 있는데,이 메소드는 정확히이 메소드를 필요로하지만 그렇지 않습니다.

foreach 루프를 사용하여 Stream을 반복하려면 다음과 같은 작업을 수행해야합니다

public static Iterable<T> getIterable(Stream<T> s) {
    return new Iterable<T> {
        @Override
        public Iterator<T> iterator() {
            return s.iterator();
        }
    };
}

for (T element : getIterable(s)) { ... }

여기에 뭔가 빠졌습니까?



답변

사람들은 이미 메일 링리스트 ☺ 에서 같은 것을 요청했습니다 . 주요 이유는 Iterable에도 반복 가능한 의미가 있지만 Stream은 그렇지 않습니다.

주된 이유는 Iterable재사용 성 을 의미하는 반면, Stream한 번만 사용할 수있는 것 Iterator입니다.

경우 Stream확장 Iterable후 기존의 코드가 놀랄 수 그것은받을 때 Iterable슬로우 Exception그들이 두 번째 시간 for (element : iterable).


답변

개종하기 Stream에를 Iterable, 당신은 할 수있다

Stream<X> stream = null;
Iterable<X> iterable = stream::iterator

를 전달하는 Stream방법에 기대하는 Iterable,

void foo(Iterable<X> iterable)

간단히

foo(stream::iterator) 

그러나 아마도 재미있을 것 같습니다. 좀 더 명확하게하는 것이 좋습니다.

foo( (Iterable<X>)stream::iterator );


답변

나는 StreamEx구현 Iterable(및 Stream)뿐만 아니라에서 잃어버린 엄청나게 멋진 기능을 제공 한다고 지적하고 싶습니다 Stream.


답변

for다음과 같이 루프 에서 스트림을 사용할 수 있습니다 .

Stream<T> stream = ...;

for (T x : (Iterable<T>) stream::iterator) {
    ...
}

( 이 코드를 여기에서 실행 하십시오 )

(이것은 Java 8 기능 인터페이스 캐스트를 사용합니다.)

(이것은 위의 주석 중 일부 (예 : Aleksandr Dubinsky )에서 다루지 만 더 잘 보이게하기 위해 답변으로 가져 가고 싶었습니다.)


답변

kennytm 설명 그것은을 치료하는 데 안전하지 않은 이유 Streamint로서 Iterable, 그리고 종 유는 해결 방법이 제공 를 사용하여 허용 Stream같이 Iterable안전하지 않은 방식으로 불구을. 두 세계의 장점을 모두 얻을 수 있습니다. 사양 Iterable에서 제공하는 Stream모든 보증을 충족 하는 재사용이 가능 Iterable합니다.

참고 : SomeType여기서는 유형 매개 변수가 아닙니다. 적절한 유형 (예 :)으로 바꾸 String거나 반사에 의존해야합니다.

Stream<SomeType> stream = ...;
Iterable<SomeType> iterable = stream.collect(toList()):

한 가지 큰 단점이 있습니다.

지연 반복의 이점은 사라집니다. 현재 스레드의 모든 값을 즉시 반복하려는 경우 오버 헤드는 무시할 수 있습니다. 그러나 부분적으로 또는 다른 스레드에서만 반복을 계획하는 경우이 즉각적이고 완전한 반복이 의도하지 않은 결과를 초래할 수 있습니다.

물론 가장 큰 장점은을 재사용 할 수 Iterable있지만 (Iterable<SomeType>) stream::iterator한 번만 사용할 수 있다는 것입니다. 수신 코드가 콜렉션에 대해 여러 번 반복되는 경우 이는 필수 일뿐만 아니라 성능에 유리할 수 있습니다.


답변

Stream구현하지 않습니다 Iterable. 일반적인 이해는 Iterable반복해서 반복 될 수있는 모든 것입니다. Stream재생할 수 없습니다.

내가 생각할 수있는 유일한 해결 방법은 스트림을 기반으로 반복 가능을 재생할 수있는 경우 스트림을 다시 만드는 것입니다. 내가 사용하고 Supplier스트림의 새로운 인스턴스를 만들려면 아래, 매번 새로운 반복자가 생성됩니다.

    Supplier<Stream<Integer>> streamSupplier = () -> Stream.of(10);
    Iterable<Integer> iterable = () -> streamSupplier.get().iterator();
    for(int i : iterable) {
        System.out.println(i);
    }
    // Can iterate again
    for(int i : iterable) {
        System.out.println(i);
    }


답변

타사 라이브러리를 사용하는 것이 마음에 들지 않으면 cyclops-react 는 Stream과 Iterable을 모두 구현하고 재생할 수있는 Stream을 정의합니다 ( kennytm 설명 문제 해결 ).

 Stream<String> stream = ReactiveSeq.of("hello","world")
                                    .map(s->"prefix-"+s);

또는 :-

 Iterable<String> stream = ReactiveSeq.of("hello","world")
                                      .map(s->"prefix-"+s);

 stream.forEach(System.out::println);
 stream.forEach(System.out::println);

[공개 나는 사이클롭스 반응의 주요 개발자입니다]