我知道这些方法的执行顺序不同,但在我的所有测试中,我都无法实现不同的顺序执行.
例:
System.out.println("forEach Demo");
Stream.of("AAA","BBB","CCC").forEach(s->System.out.println("Output:"+s));
System.out.println("forEachOrdered Demo");
Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("Output:"+s));
Run Code Online (Sandbox Code Playgroud)
输出:
forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC
Run Code Online (Sandbox Code Playgroud)
请提供两种方法产生不同输出的示例.
Javadoc Stream.forEach表示(强调我的):
此操作的行为明确是不确定的.对于并行流管道,此操作不保证遵守流的遭遇顺序,因为这样做会牺牲并行性的好处.对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.如果操作访问共享状态,则它负责提供所需的同步.
Java 9 Early Access Javadoc中提供了相同的文本.
第一句("明确不确定")表明(但没有明确说明)此方法不会保留遭遇顺序.但是明确说明顺序没有保留的下一个句子是以"For parallel stream pipeline"为条件的,如果不管并行性如何应用该句子,那么这个条件就没有了.这让我不确定forEach是否会保留顺序流的顺序.
这个答案指出了流库实现调用的位置.sequential().forEach(downstream).这表明forEach旨在保留顺序流的顺序,但也可能只是库中的错误.
我通过使用forEachOrdered安全的方式回避了我自己的代码中的这种模糊性,但今天我发现NetBeans IDE的"使用功能操作"编辑器提示将转换
for (Foo foo : collection)
foo.bar();
Run Code Online (Sandbox Code Playgroud)
成
collection.stream().forEach((foo) -> {
foo.bar();
});
Run Code Online (Sandbox Code Playgroud)
如果forEach不保留遭遇顺序,则会引入错误.在我报告针对NetBeans的错误之前,我想知道库实际上保证了什么,并由源备份.
我正在寻找权威人士的答案.这可能是图书馆实施中的一个明确的评论,关于Java开发邮件列表的讨论(谷歌没有找到任何东西,但我可能不知道这些神奇的词汇),或者是图书馆设计师的声明(其中我知道两个,Brian Goetz和Stuart Marks,积极参与Stack Overflow).(请不要回答"只是使用forEachOrdered" - 我已经这样做了,但我想知道代码是否错误.)