Stream Guru 的问题很简单:
我有这个:
List<MyBean> beans = new ArrayList<>();
beans.add(new MyBean("tutu"));
beans.add(new MyBean("toto"));
beans.add(new MyBean("titi"));
比较:
StringBuilder reduced
= beans.parallelStream()
.map(MyBean::getName)
.reduce(new StringBuilder(), (builder, name) -> {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(name);
return builder;
}, (left, right) -> left.append(right));
和
StringBuilder reduced
= beans.parallelStream()
.map(MyBean::getName)
.reduce(new StringBuilder(), (builder, name) -> {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(name);
return builder;
}/* WITHOUT THIRD PARAM*/);
为什么,第二个解决方案无法编译...第三个参数用于并行流...
您能解释一下为什么我无法编译第二个代码部分吗?
最佳答案
此行为是因为 reduce 的重载:
reduce(T identity, BinaryOperator<T> accumulator)
接受两个参数,第二个是 BinaryOperator<T>
它基本上表示对两个相同类型的操作数 的操作,产生与操作数相同类型的结果。在你的第二个代码片段中没有遵守这个契约(Contract)作为你的 map
操作返回 Stream<String>
而 identity 的类型是 StringBuilder
.为防止编译器错误,只需将 identity 值和 accumulator 函数的操作数设为相同类型即可,即:
StringBuilder reduced
= beans.stream()
.map(b -> new StringBuilder(b.getName()))
.reduce(new StringBuilder(), (builder, name) -> {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(name);
return builder;
}/* WITHOUT THIRD PARAM*/);
另一方面, reduce
的重载:
reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
接受 BiFunction
作为第二个参数,它可以使用两种不同类型的对象,这就是为什么您的第一个代码片段可以正常运行而不会出现编译器错误的原因。
最后,不要忘记更改 beans.parallelStream()
至 beans.stream()
如上面的解决方案所示。
顺便说一句,请注意,在并行执行操作时,累加器以及组合器必须为associative , non-interfering和 stateless .如果不考虑这一点,您的结果将是非确定性任意结果。
编辑:
如 Holger 所述:
Modifying incoming parameters in a reduction function is broken by definition, even if it happens to produce the intended outcome in a sequential context. It also violates the contract of the first parameter, as the modified
StringBuilder
is not an identity value anymore. You can use Reduction with immutable values, as.map(MyBean::getName).reduce((a,b) -> a + ", " + b).orElse("");
or use Mutable Reduction like.map(MyBean::getName).collect(Collectors.joining(", "));
关于java - 第三个参数 Java8 reduce on Object 中的字符串属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47541611/