gpt4 book ai didi

java - Java 8 reduce BinaryOperator 的用途是什么?

转载 作者:搜寻专家 更新时间:2023-10-31 08:12:04 24 4
gpt4 key购买 nike

我目前正在阅读 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());

这会产生正确的输出。

先生:John Lennon,先生:Paul Mccartney,先生:George Harrison,先生:Ringo Starr

我的问题是关于 reduce 方法的最后一个参数,它是一个 BinaryOperator

这个参数有什么用?如果我改变

.reduce(new StringBuilder(),accumulator,(left,right)->new StringBuilder());

输出是一样的;如果我传递 NULL,则返回 N.P.E。

这个参数有什么用?

更新

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

第一次运行:

returned StringBuilder length = 420

第二次运行:

returned StringBuilder length = 546

第三次运行:

returned StringBuilder length = 348

等等。这是为什么 - 它不应该在每次迭代时返回所有值吗?

最佳答案

接口(interface)Stream 中的方法reduce 被重载。具有三个参数的方法的参数是:

  • 身份
  • 蓄能器
  • 组合器

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

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

这是一个示例,说明如何使用 combiner 将顺序缩减转换为支持并行执行的缩减。有一个包含四个 String 的流,acc 用作 accumulator.apply 的缩写。那么缩减的结果可以计算如下:

acc(acc(acc(acc(identity, "one"), "two"), "three"), "four");

使用兼容的组合器,上面的表达式可以转换为下面的表达式。现在可以在不同的线程中执行两个子表达式。

combiner.apply(
acc(acc(identity, "one"), "two"),
acc(acc(identity, "three"), "four"));

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

BiFunction<StringBuilder,String,StringBuilder> accumulator =
(builder,name) -> builder.append(name);

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

acc(acc(acc(identity, "one"), "two"), "three")  
acc(acc(identity, "one"), acc(acc(identity, "two"), "three"))

上面的累加器不是这样。问题是,您正在改变 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);

关于java - Java 8 reduce BinaryOperator 的用途是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23980888/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com