Java 8减少BinaryOperator用于什么?

chi*_*tiz 5 java binary-operators java-8

我目前正在阅读O'reilly Java 8 Lambdas是一本非常好的书.我遇到过这样的例子.

我有一个

private final BiFunction<StringBuilder,String,StringBuilder>accumulator=
(builder,name)->{if(builder.length()>0)builder.append(",");builder.append("Mister:").append(name);return builder;};

final Stream<String>stringStream = Stream.of("John Lennon","Paul Mccartney"
,"George Harrison","Ringo Starr");
final StringBuilder reduce = stringStream
    .filter(a->a!=null)
    .reduce(new StringBuilder(),accumulator,(left,right)->left.append(right));
 System.out.println(reduce);
 System.out.println(reduce.length());
Run Code Online (Sandbox Code Playgroud)

这产生了正确的输出.

Mister:John Lennon,Mister:Paul Mccartney,Mister:George Harrison,Mister:Ringo Starr

我的问题被认为是reduce最后一个参数的方法BinaryOperator

我的问题是这个参数用于哪个?如果我改变

.reduce(new StringBuilder(),accumulator,(left,right)->new StringBuilder());
Run Code Online (Sandbox Code Playgroud)

如果我通过,NULL那么输出是相同的,然后返回NPE.

这个参数用于什么?

UPDATE

为什么如果我运行它parallelStream我收到不同的结果?

第一次运行.

returned StringBuilder length = 420
Run Code Online (Sandbox Code Playgroud)

第二轮

returned StringBuilder length = 546
Run Code Online (Sandbox Code Playgroud)

第三次运行

returned StringBuilder length = 348
Run Code Online (Sandbox Code Playgroud)

等等?为什么这个...不应该在每次迭代时返回所有值?

任何帮助都非常感激.

谢谢.

nos*_*sid 14

reduce接口中的方法Stream被重载.具有三个参数的方法的参数是:

  • 身分
  • 累加器
  • 组合

combiner支持的并行执行.显然,它不用于顺序流.但是,没有这样的保证.如果您将更改为并行流,我猜您会看到不同之处:

Stream<String>stringStream = Stream.of(
    "John Lennon", "Paul Mccartney", "George Harrison", "Ringo Starr")
    .parallel();
Run Code Online (Sandbox Code Playgroud)

下面是一个示例,说明如何将combiner顺序缩减转换为缩减,支持并行执行.有一个带有四个Strings 的流,acc用作缩写accumulator.apply.然后,减少的结果可以计算如下:

acc(acc(acc(acc(identity, "one"), "two"), "three"), "four");
Run Code Online (Sandbox Code Playgroud)

通过兼容combiner,可以将上述表达式转换为以下表达式.现在可以在不同的线程中执行两个子表达式.

combiner.apply(
    acc(acc(identity, "one"), "two"),
    acc(acc(identity, "three"), "four"));
Run Code Online (Sandbox Code Playgroud)

关于你的第二个问题,我使用简化accumulator来解释问题:

BiFunction<StringBuilder,String,StringBuilder> accumulator =
    (builder,name) -> builder.append(name);
Run Code Online (Sandbox Code Playgroud)

根据Javadoc for Stream :: reduce,accumulator它必须是关联的.在这种情况下,这意味着,以下两个表达式返回相同的结果:

acc(acc(acc(identity, "one"), "two"), "three")  
acc(acc(identity, "one"), acc(acc(identity, "two"), "three"))
Run Code Online (Sandbox Code Playgroud)

对于上述情况,情况并非如此accumulator.问题是,您正在改变引用的对象identity.这对于reduce手术来说是一个坏主意.以下是两个可行的替代实现:

// identity = ""
BiFunction<String,String,String> accumulator = String::concat;

// identity = null
BiFunction<StringBuilder,String,StringBuilder> accumulator =
    (builder,name) -> builder == null
        ? new StringBulder(name) : builder.append(name);
Run Code Online (Sandbox Code Playgroud)