有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

流的java行为。传递供应商<Stream<T>>参数时生成方法

在阅读了this questionone of its answers之后,我决定自己运行一些测试。令我惊讶的是,我遇到了一个看起来很奇怪的情况

代码如下:

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

正如您所看到的,repeatFromSupplierrepeatFromStream方法之间的区别在于它的参数和传递给Stream.generate方法的内容

repeatFromSupplier方法接收类型为Supplier<Stream<T>>的参数并将该参数直接传递给Stream.generate方法时,repeatFromStream方法接收类型为Stream<T>的参数并通过() -> stream内联lambda表达式创建Supplier<Stream<T>>,该表达式立即传递给Stream.generate方法

我希望这两种方法表现出相同的行为,因为我认为这些差异只是表面上的

然而,这段代码显示了repeatFromSupplierrepeatFromStream方法的不同行为。如果运行它,您会注意到repeatFromSupplier方法按预期工作(它打印1231231231),而repeatFromStream方法打印123并抛出IllegalStateException: stream has already been operated upon or closed

现在,我确实知道了抛出此异常的原因和时间。我不是在问这件事。相反,我想知道为什么这两种方法表现不同


共 (1) 个答案

  1. # 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);
    

    这也引发了一个例外