【发布时间】:2015-05-29 09:44:43
【问题描述】:
Java API 文档指出collect 方法的combiner 参数必须是:
用于组合两个值的关联、无干扰、无状态函数,必须与累加器函数兼容
combiner 是一个BiConsumer<R,R>,它接收两个R 类型的参数并返回void。但是文档没有说明我们是否应该将元素组合到第一个或第二个参数中?
例如,以下示例可能会给出不同的结果,具体取决于组合顺序为:m1.addAll(m2) 或 m2.addAll(m1)。
List<String> res = LongStream
.rangeClosed(1, 1_000_000)
.parallel()
.mapToObj(n -> "" + n)
.collect(ArrayList::new, ArrayList::add,(m1, m2) -> m1.addAll(m2));
我知道在这种情况下我们可以简单地使用方法句柄,例如ArrayList::addAll。然而,在某些情况下需要 Lambda,我们必须以正确的顺序组合项目,否则在并行处理时可能会得到不一致的结果。
这在 Java 8 API 文档的任何部分中都有声明吗?还是真的没关系?
【问题讨论】:
-
你说得对,javadoc 写得不是很清楚——令人困惑的是,它说组合器必须是关联的!它可能是早期版本的遗留物,它使用
BinaryOperator而不是BiConsumer。但是从给定的示例中可以清楚地看出,组合器必须累积到它的第一个参数中。
标签: java java-8 java-stream