Java 有序流上的减少是否按顺序减少?
我有一个a、B、C的Java 有序流上的减少是否按顺序减少?,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个a、B、C的列表 C减少A减少B!=A reduce B reduce C(但是,A reduce(B reduce C)可以) 换句话说,我的约化运算是关联的,但不是交换的 java是否在有序的顺序流(例如列表中的默认流)上强制执行减少总是根据遭遇顺序进行的?也就是说,java是否会重新排序缩减(使B减少A而不是A减少B) (希望这足够清楚) 编辑以添加一个小演示,可能有助于澄清 Stream.of(" cats ", " eat ", " bats ") .reduce("",
列表
C减少A减少B!=A reduce B reduce C
(但是,A reduce(B reduce C)可以)
换句话说,我的约化运算是关联的,但不是交换的
java是否在有序的顺序流(例如列表中的默认流)上强制执行减少总是根据遭遇顺序进行的?也就是说,java是否会重新排序缩减(使B减少A而不是A减少B)
(希望这足够清楚)
编辑以添加一个小演示,可能有助于澄清
Stream.of(" cats ", " eat ", " bats ")
.reduce("", (a, b) -> a + b); // cats eat bats
有了以上这些,输出会是“蝙蝠猫吃”还是“吃蝙蝠猫”?这在规范中有保证吗?根据规范,它尊重元素的顺序
证明很简单。要求缩减函数必须是关联的
但是,如果不保留顺序,关联性本身就没有任何意义。根据关联属性的定义:
在包含一行中两个或多个引用的表达式中
相同的关联运算符,即操作的顺序
只要操作数序列是
未更改
换句话说,关联属性并不意味着:
(a + b) + c = (a + c) + b
它只允许对应用操作的顺序进行任意排列。当您使用文档时,会显示:
返回其元素为指定值的有序流
在这一点上,您知道您有一个有序的顺序流,并且
对于连续流,相遇顺序的存在或不存在并不影响性能,只影响确定性如果对流进行排序,则在相同源上重复执行相同的流管道将产生相同的结果;如果不进行排序,重复执行可能会产生不同的结果
仅关于reduce
操作,当顺序流存在顺序时,结果应相同,即使对于并行顺序流,操作也将保持最终顺序(至少在当前的java8和java9实现中,将来可以进行一些优化,但是使用reduce
的有序流的顺序可能永远不会改变)
您必须仔细了解流的排序时间。例如,像map
或filter
这样的操作会保留流的顺序,因此如果您有一个已排序的流,您可以使用此方法,流将继续排序
注意:排序与排序完全不同
如果一个流是有序的,那么大多数操作都会被约束为按遭遇顺序对元素进行操作;如果一个流的源是一个包含[1,2,3]的列表,那么执行map(x->x*2)的结果必须是[2,4,6]
编辑(根据评论):
但不限于按顺序执行
这就是为什么关联性是必要的,例如,如果您有一个从这样的数组生成的流{a
,b
,c
,d
,那么a
+b
可以首先解析,然后c
+d
,最后一起解析(a
+b
)(c
+d
),这就是为什么操作必须是关联的。这样,如果操作确实是关联的(必须是关联的),那么最终的顺序将被保留
我所关心的是reduce文档中的这条简介“这相当于……但不限于按顺序执行。”
允许流管道执行“cats”+(“eat”+“bats”)
或(“cats”+“eat”)+“bats”
您在一个问题中问了两个问题
java是否在有序的顺序流(例如列表中的默认流)上强制执行减少总是根据遭遇顺序进行的
假设“总是会发生”是指函数求值的顺序,答案是否定的,这是不能保证的
有了以上内容,输出会是“蝙蝠猫吃”还是“蝙蝠猫吃”?这在规范中有保证吗
无论归约函数的求值顺序(处理顺序)如何,结果都保证是“猫吃蝙蝠”
,正确反映遭遇顺序(另请参见).为确保未指定的处理顺序仍然产生关于遭遇顺序的正确结果,缩减函数必须是关联的
请注意,甚至将.reduce(“,String::concat)
作为有效但低效的缩减函数的示例。类似地,(a,b)->b
作为获取流的最后一个元素的有效方法
关键点见下表:
结合性
如果以下条件成立,则运算符或函数op
是关联的:
(a op b) op c == a op (b op c)
如果我们将其扩展到四个术语,就可以看出这对平行评估的重要性:
a op b op c op d == (a op b) op (c op d)
因此,我们可以与(c op d)
并行计算(a op b)
,然后对结果调用op
关联操作的示例包括数字相加、最小值和最大值以及字符串连接
@Andremoniy@shmosel好的,但这是列表的缩减,而不是特定的列表元素的缩减!!@Andremoniy我想它的意思是
op.apply(op.apply(a,b),c)
,其中op
是二进制运算符
@DD你已经设法让事情变得更加混乱了。@shmoselreduce(“,(a,b)->a++b)
将违反有关身份价值的合同,
a op b op c op d == (a op b) op (c op d)