IT story

스트리밍하는 이유

hot-time 2020. 4. 5. 20:35
반응형

스트리밍하는 이유 Iterable을 구현하지 않음?


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.


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

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

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

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

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

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


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

Stream<T> stream = ...;

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

( 이 스 니펫을 여기서 실행 하십시오 )

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

(이것은 위의 주석 중 일부에 포함되어 있지만 (예 : Aleksandr Dubinsky ) 더 잘 보이도록 답변으로 끌어 내고 싶었습니다.)


타사 라이브러리를 사용하는 것이 마음에 들지 않으면 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);

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


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

완벽하지는 않지만 작동합니다.

iterable = stream.collect(Collectors.toList());

이 스트림에서 모든 항목을 가져오고 그에 넣어 때문에 완벽하지 List정확히하지 않은, Iterable그리고 Stream에 대한 있습니다. 그들은 게으른 것으로 추정된다 .


다음 Stream<Path>과 같이 사용하여 폴더의 모든 파일을 반복 할 수 있습니다 .

Path path = Paths.get("...");
Stream<Path> files = Files.list(path);

for (Iterator<Path> it = files.iterator(); it.hasNext(); )
{
    Object file = it.next();

    // ...
}

참고 URL : https://stackoverflow.com/questions/20129762/why-does-streamt-not-implement-iterablet

반응형