考虑以下代码:
urls.stream()
.flatMap(url -> fetchDataFromInternet(url).stream())
.filter(...)
.findFirst()
.get();
当第一个URL足够时,fetchDataFromInternet
会被调用第二次吗?
我尝试了一个更小的示例,看起来像预期的工作方式。即逐个处理数据,但是这种行为可靠吗?如果不是,那么在.flatMap(...)
之前调用.sequential()
是否有帮助?
Stream.of("one", "two", "three")
.flatMap(num -> {
System.out.println("Processing " + num);
// return FetchFromInternetForNum(num).data().stream();
return Stream.of(num);
})
.peek(num -> System.out.println("Peek before filter: "+ num))
.filter(num -> num.length() > 0)
.peek(num -> System.out.println("Peek after filter: "+ num))
.forEach(num -> {
System.out.println("Done " + num);
});
输出:
Processing one
Peek before filter: one
Peek after filter: one
Done one
Processing two
Peek before filter: two
Peek after filter: two
Done two
Processing three
Peek before filter: three
Peek after filter: three
Done three
更新:如果实现方案很重要,使用官方Oracle JDK8。
答案: 根据下面的评论和答案,flatmap部分是惰性的。也就是说,它会完全读取第一个流,并且只有在需要时才进行下一个流的读取。读取一个流是急切的,但读取多个流是惰性的。
如果此行为是有意的,API应该允许函数返回Iterable
而不是流。
换句话说:链接
.sequential()
。 - teppicfetchDataFromInternet
不会被多次调用,但是特定的fetchDataFromInternet
调用返回的元素可能会在没有延迟处理的情况下被处理。 - Holger