有序流上的减少是按顺序减少的吗?

Cog*_*man 7 java java-8 java-stream

我有一个ListA,B,C.

C reduce A reduce B != A reduce B reduce C (但是,减少(B减少C)是可以的).

换句话说,我的还原操作是关联的,但不是可交换的.

java是否对有序顺序流(例如列表中的默认流)执行减少将始终根据遭遇顺序进行减少?也就是说,java会重新排序减少(这样B减少A而不是A减少B)?

(希望这很清楚).

编辑添加一个小演示,也许有助于澄清

Stream.of(" cats ", " eat ", " bats ")
  .reduce("", (a, b) -> a + b); // cats eat bats
Run Code Online (Sandbox Code Playgroud)

有了上述,输出可能是"蝙蝠猫吃"​​或"吃蝙蝠猫"?是否在规范的某处保证了?

And*_*niy 6

我之前的回答是不正确的(感谢@shmosel纠正我).

现在我说,根据规范,它尊重元素的顺序.

证明非常简单.该说明书声称还原功能必须是 关联的.

但是,如果没有保留订单,它自身的关联性就没有任何意义.根据关联属性的数学定义:

在同一关联运算符的一行中包含两个或更多个出现的表达式中,只要操作数的顺序 没有改变,执行操作的顺序就无关紧要.

换句话说,关联属性并不意味着:

(a + b) + c = (a + c) + b
Run Code Online (Sandbox Code Playgroud)

它只允许对应用操作的顺序进行任意排列.


Hol*_*ger 5

您已将两个问题合二为一。

  1. java 是否对有序的顺序流(例如列表中的默认流)强制执行减少总是根据遇到顺序发生的?

假设“永远会发生”是指函数求值的顺序,答案是否定的,这不能保证。

  1. Stream.of(" cats ", " eat ", " bats ")
      .reduce("", (a, b) -> a + b); // cats eat bats
    
    Run Code Online (Sandbox Code Playgroud) 有了上述内容,输出可能是“蝙蝠猫吃”​​或“吃蝙蝠猫”吗?这在规范中的某处有保证吗?

无论归约函数的评估顺序(处理顺序)如何,结果都保证是" cats eat bats ",正确反映遇到顺序(另请参阅此答案)。为了确保未指定的处理顺序仍然产生关于遇到顺序的正确结果,归约函数必须是关联的如指定的

请注意,文档甚至显示.reduce("", String::concat)了一个有效但效率低下的归约函数示例。同样,(a,b) -> b 已被公认为获取流的最后一个元素的有效方法。

文档“关联性”部分给出了关键点:

关联性

如果满足以下条件,则运算符或函数op关联的:

(a op b) op c == a op (b op c)
Run Code Online (Sandbox Code Playgroud)

如果我们将其扩展为四个术语,则可以看出这对并行评估的重要性:

a op b op c op d == (a op b) op (c op d)
Run Code Online (Sandbox Code Playgroud)

因此,我们可以(a op b)与 并行评估(c op d),然后op对结果进行调用。

关联运算的示例包括数字加法、最小值和最大值以及字符串连接。