第三个参数Java8减少了Object中的字符串属性

use*_*486 2 java reduce lambda java-8 java-stream

Stream Guru的问题非常简单:

我有这个:

    List<MyBean> beans = new ArrayList<>();
    beans.add(new MyBean("tutu"));
    beans.add(new MyBean("toto"));
    beans.add(new MyBean("titi"));
Run Code Online (Sandbox Code Playgroud)

比较:

 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));
Run Code Online (Sandbox Code Playgroud)

 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*/);
Run Code Online (Sandbox Code Playgroud)

为什么,第二个解决方案没有编译...第三个参数是针对并行流...

你能解释为什么我无法编译第二个代码部分吗?

Ous*_* D. 5

这种行为是因为这个重载减少了:

reduce(T identity, BinaryOperator<T> accumulator)
Run Code Online (Sandbox Code Playgroud)

取两个参数,第二个是a BinaryOperator<T>,它基本上表示对两个相同类型的操作数的操作,产生与操作数相同类型的结果.在您的第二个代码片段中未遵循此合同,因为您的map操作返回a Stream<String>标识属于类型StringBuilder.为了防止编译器错误,只需使标识值以及累加器函数的操作数都是相同的类型,即:

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*/);
Run Code Online (Sandbox Code Playgroud)

另一方面这种超载reduce:

reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Run Code Online (Sandbox Code Playgroud)

接受一个BiFunction可以消耗两种不同类型对象的第二个参数,这就是为什么你的第一个代码片段在没有编译器错误的情况下工作的原因.

最后,不要忘记更改上面的解决方案中显示的beans.parallelStream()to beans.stream().

顺便说一句,请注意,在并行执行操作时,所述蓄能器,以及所述组合器,必须缔合,无干扰无状态.如果不考虑这一点,您的结果将是不确定的任意结果.

编辑:

正如霍尔格所说:

在定义中修改递减函数中的传入参数,即使它恰好在顺序上下文中产生预期结果.它还违反了第一个参数的合同,因为修改后的参数StringBuilder不再是标识值.你可以使用Reducing with immutable values, .map(MyBean::getName).reduce((a,b) -> a + ", " + b).orElse("");或者使用Mutable Reduction .map(MyBean::getName).collect(Collectors.joining(", "));

  • 这不仅仅是旁注.在定义中修改递减函数中的传入参数,即使它恰好在顺序上下文中产生预期结果.它还违反了第一个参数的约定,因为修改后的`StringBuilder`不再是一个标识值.您可以使用Reducing with immutable values,如`.map(MyBean :: getName).reduce((a,b) - > a +","+ b).orElse("")`或使用像`的Mutable Reduction. map(MyBean :: getName).collect(Collectors.joining(","))`... (2认同)