流的java行为。传递供应商<Stream<T>>参数时生成方法
在阅读了this question和one 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);
}
}
正如您所看到的,repeatFromSupplier
和repeatFromStream
方法之间的区别在于它的参数和传递给Stream.generate
方法的内容
当repeatFromSupplier
方法接收类型为Supplier<Stream<T>>
的参数并将该参数直接传递给Stream.generate
方法时,repeatFromStream
方法接收类型为Stream<T>
的参数并通过() -> stream
内联lambda表达式创建Supplier<Stream<T>>
,该表达式立即传递给Stream.generate
方法
我希望这两种方法表现出相同的行为,因为我认为这些差异只是表面上的
然而,这段代码显示了repeatFromSupplier
和repeatFromStream
方法的不同行为。如果运行它,您会注意到repeatFromSupplier
方法按预期工作(它打印1231231231
),而repeatFromStream
方法打印123
并抛出IllegalStateException: stream has already been operated upon or closed
现在,我确实知道了抛出此异常的原因和时间。我不是在问这件事。相反,我想知道为什么这两种方法表现不同
# 1 楼答案
在
s1
的名义情况下,您每次都会呼叫供应商创建一个新流:但是在
s2
的情况下,您创建一个流,然后始终从供应商返回相同的实例:这与以下代码基本相同:
这也引发了一个例外