考虑以下代码:
urls.stream()
.flatMap(url -> fetchDataFromInternet(url).stream())
.filter(...)
.findFirst()
.get();
fetchDataFromInternet
当第一个URL够用时会被要求输入第二个URL吗?
我尝试了一个较小的示例,它看起来像预期的那样工作。即一个一个地处理数据,但是可以依靠这种行为吗?如果没有,.sequential()
在.flatMap(...)
帮助之前打电话吗?
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
而不是一个流。
在当前的实现下 ,flatmap
渴望;像任何其他有状态中间操作(如sorted
和distinct
)一样。而且很容易证明:
int result = Stream.of(1)
.flatMap(x -> Stream.generate(() -> ThreadLocalRandom.current().nextInt()))
.findFirst()
.get();
System.out.println(result);
从来没有像flatMap
渴望的那样完成。例如:
urls.stream()
.flatMap(url -> fetchDataFromInternet(url).stream())
.filter(...)
.findFirst()
.get();
这意味着,对于每个url
,flatMap
即使您只关心单个操作,也将阻止其后的所有其他操作。因此,让我们假设,从url
您的fetchDataFromInternet(url)
生成10_000
行中,即使您只关心一行,您findFirst
也将不得不等待
所有 10_000的计算。
编辑
这在Java 10中已得到修复,在Java
10中我们恢复了懒惰:请参阅JDK-8075939
编辑2
这也已在Java
8(8u222)中修复:JDK-8225328
输出: 如果要执行此行为,API应该让函数返回而不是流。 换句话说:链接
问题内容: 例如,如果我有以下语句: 如果foo1为true,python将检查foo2的条件吗? 问题答案: 是的,Python懒惰地评估布尔条件。 该文件说, 表达式x和y首先计算x;如果x为假,则返回其值;否则,将评估y并返回结果值。 表达式x或y首先计算x; 如果x为true,则返回其值;否则,将评估y并返回结果值。
问题内容: 我在Linux上编写了一个C程序,该程序可以分配内存,并在一个循环中运行它,而TOP没有显示任何内存消耗。 然后我对该内存做了一些操作,而TOP确实显示了内存消耗。 当我分配内存时,我真的是“获取内存”,还是有一个“惰性”内存管理,仅当使用时才给我内存? (还有一个选项,当我使用它时,TOP只知道内存消耗,因此我不确定。) 谢谢 问题答案: 在Linux上,malloc使用sbrk()
问题内容: 众所周知,JavaScript在所有现代浏览器实现中都是单线程的,但是它是在任何标准中指定的,还是仅根据传统?假设JavaScript始终是单线程的,是否完全安全? 问题答案: 这是个好问题。我很想说“是”。我不能 通常认为JavaScript具有脚本(*)可见的单个执行线程,因此,当您输入内联脚本,事件侦听器或超时时,您将完全处于控制状态,直到从块或函数的结尾返回为止。 (*:忽略浏
问题内容: 我真的是在这里指身份平等。 例如,以下内容将始终打印 true 吗? 问题答案: 是的,类令牌是唯一的(对于任何给定的类加载器而言)。 即,您将始终 在相同的类加载器领域中 获得对相同物理对象的引用。但是,不同的类加载器将加载不同的类令牌,同时,当两个不同的类加载器加载相同的类定义时,会将相同的类定义视为不同。
问题内容: PHP手册指出返回  “ 当前UNIX时间戳” ᴀ  和返回 “当前Unix时间戳和微秒” ʙ。 但是,是否 保证 这些功能的行为类似于严格符合POSIX.1的系统的行为? 具体来说,是否插入leap秒,使  |  的输出 在第二天的开始(也就是the秒的结尾) 向后* 跳1秒(在第二天的第一秒的整个过程中)