The behavior of the Stream.generate method when passing a provider argument <Stream <T>>

After reading this question and one of my answers, I decided to independently perform some tests. To my surprise, I came to a situation that looks rather strange.

Here is the code:

public class InfiniteRepeatingStream {

    public static void main(String[] args) {

        Stream<Integer> s1 = repeatFromSupplier(() -> Stream.of(1, 2, 3));
        s1.sequential().limit(10).forEachOrdered(System.out::print);

        System.out.print("\n----------------\n");

        Stream<Integer> s2 = repeatFromStream(Stream.of(1, 2, 3));
        s2.sequential().limit(10).forEachOrdered(System.out::print);
    }

    static <T> Stream<T> repeatFromSupplier(Supplier<Stream<T>> supplier) {
        return Stream.generate(supplier).flatMap(s -> s);
    }

    static <T> Stream<T> repeatFromStream(Stream<T> stream) {
        return Stream.generate(() -> stream).flatMap(s -> s);
    }
}

As you can see, the difference between the methods repeatFromSupplierand repeatFromStreamis lying on his argument and that is passed to the method Stream.generate.

While the method repeatFromSupplierreceives the type argument Supplier<Stream<T>>and passes this argument directly to the method Stream.generate, the method repeatFromStreamreceives the type argument Stream<T>and creates an Supplier<Stream<T>>expression from the built-in lambda () -> streamthat is immediately passed to the method Stream.generate.

, , , .

repeatFromSupplier repeatFromStream. , , repeatFromSupplier ( 1231231231), repeatFromStream 123 IllegalStateException: stream has already been operated upon or closed.

, . . , -.

+4
1

s1 :

() -> Stream.of(1, 2, 3)

s2 , :

() -> stream

, :

Stream<Integer> s = Stream.of(1, 2, 3); // now Stream.of is only executed once
Stream<Integer> s1 = repeatFromSupplier(() -> s);
s1.sequential().limit(10).forEachOrdered(System.out::print);

.

+4

Source: https://habr.com/ru/post/1691802/


All Articles