在阅读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
方法接收类型为{{1}的参数并通过Stream<T>
内联lambda表达式创建Supplier<Stream<T>>
,该表达式立即传递给() -> stream
方法。
我希望这两种方法都表现出相同的行为,因为我认为差异只是美化。
但是,此代码显示Stream.generate
和repeatFromSupplier
方法的不同行为。如果您运行它,您会注意到repeatFromStream
方法按预期工作(它打印repeatFromSupplier
),而1231231231
方法打印repeatFromStream
并抛出{ {1}}。
现在,我知道为什么以及何时抛出此异常。我不是在询问它。相反,我想知道为什么两种方法的行为都不同。
答案 0 :(得分:4)
在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);
这也引发了异常。