reduce()方法如何与Java 8中的并行流一起使用?

时间:2019-05-07 13:13:12

标签: java arrays java-8 java-stream stringbuilder

我尝试了解reduce()方法如何与并行流完全兼容,并且我不理解为什么以下代码不返回这些字符串的串联。

这是代码:

public class App {

    public static void main(String[] args) {
        String[] grades = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"};

        StringBuilder concat = Arrays.stream(grades).parallel()
                .reduce(new StringBuilder(),
                        (sb, s) -> sb.append(s),
                        (sb1, sb2) -> sb1.append(sb2));

        System.out.println(concat);

    }
}

该代码仅适用于顺序流,但不适用于并行流,它不返回串联。每次输出都不同。有人可以解释一下那里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

问题是您将Stream::reduce用于Mutable reduction,而Stream::collect是专门为Streams: Reduction设计的。它可以用于安全的并行存储。还可以在Oracle官方文档reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)中了解差异。与reduce方法(在处理元素时总是会创建新值)不同,collect方法会修改或变异现有值。

从JavaDoc中注意到这两种方法之间的区别:

因此,我建议您执行以下操作:

StringBuilder concat = Arrays.stream(grades)
    .parallel()
    .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);