2015-09-26 137 views
35

我知道这些方法不同于执行顺序,但在所有测试中我都无法实现不同的顺序执行。forEach vs forEach在Java中订购8流

实施例:

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)); 

输出:

forEach Demo 
Output:AAA 
Output:BBB 
Output:CCC 
forEachOrdered Demo 
Output:AAA 
Output:BBB 
Output:CCC 

请提供范例当2种方法将产生不同的输出。

+0

尝试使用并行流。 – Pshemo

+0

@Pshemo是唯一可能的选择吗? – gstackoverflow

+3

未指定的订单并不意味着“保证是不同的订单”。它只是意味着*未指定*,这意味着匹配遇到命令的可能性。没有内置的洗牌功能。 – Holger

回答

42
Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s)); 
Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s)); 

第二行总是输出

Output:AAA 
Output:BBB 
Output:CCC 

而第一之一未guaranted因为顺序没有保留。 forEachOrdered将按照源的指定顺序处理流的元素,而不管流是顺序的还是并行的。从forEach的Javadoc

报价:

此操作的行为是明确的不确定性。对于并行流管线,此操作不保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。

forEachOrdered的Javadoc状态(重点煤矿):

执行对在流的遭遇顺序这个流,的每个元件的动作,如果该流具有规定的遭遇顺序。

+6

是的,你是对的。只有parallelStreams可能吗? – gstackoverflow

+6

即使它现在只适用于并行流 - 我不是说它会这样做 - 如果某些中间步骤已经过优化以利用无序流,它仍然可能在未来中断。如果流是无序的,排序可以使用不稳定的算法。 – the8472

+1

因此,在'parallel'中使用'forEachOrdered'是没有意义的? –

20

虽然forEach短,看起来更漂亮,我建议使用forEachOrdered在每一个地方,以便事项明确指定。对于顺序流,forEach似乎遵守顺序,甚至流API API内部代码usesforEach(对于已知为顺序的流),在语义上需要使用forEachOrdered!不过,您稍后可能会决定将您的数据流更改为并行数据,并且您的代码将被破坏。另外,当您使用forEachOrdered时,您的代码的读者会看到以下消息:“订单在这里很重要”。因此它更好地记录你的代码。

另请注意,对于并行数据流,forEach不仅以非确定性顺序执行,还可以在不同线程中同时执行不同元素(不适用于forEachOrdered)。

最后,forEach/forEachOrdered很少有用。在大多数情况下,您实际需要产生一些结果,而不仅仅是副作用,因此像reducecollect这样的操作应该更合适。通过forEach表示通过自然减少操作通常被认为是不好的风格。

+6

“最后,forEach/forEachOrdered都很少有用”。我十分同意。看来这些方法被过度使用。 – Tunaki

+0

感谢您的回答。但它不是现实生活中的例子。我只是学习java 8 – gstackoverflow

+0

为什么它在语义上有必要在代码中使用'forEachOrdered'? – RealSkeptic