Java 8 reduce BinaryOperator用于什么?
我目前正在阅读的Java 8 reduce BinaryOperator用于什么?,java,java-8,binary-operators,Java,Java 8,Binary Operators,我目前正在阅读的O'reillyjava8lambdas是一本非常好的书。我遇到了这样一个例子 我有一个 private final BiFunction<StringBuilder,String,StringBuilder>accumulator= (builder,name)->{if(builder.length()>0)builder.append(",");builder.append("Mister:").append(name);return builder
O'reilly
java8lambdas是一本非常好的书。我遇到了这样一个例子
我有一个
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());
如果我通过NULL
则返回N.p.E,则输出相同
此参数的用途是什么
更新
为什么在parallelStream
上运行它会收到不同的结果
第一轮
returned StringBuilder length = 420
第二轮
returned StringBuilder length = 546
第三轮
returned StringBuilder length = 348
等等?为什么这是。。。是否不应在每次迭代时返回所有值
任何帮助都是万分感激的
谢谢。接口
流中的方法reduce
过载。具有三个参数的方法的参数为:
- 身份
- 累加器
- 组合器
组合器支持并行执行。显然,它不用于连续流。然而,没有这样的保证。如果您将流更改为并行流,我想您会看到不同:
Stream<String>stringStream = Stream.of(
"John Lennon", "Paul Mccartney", "George Harrison", "Ringo Starr")
.parallel();
使用兼容的组合器
,可以将上述表达式转换为以下表达式。现在可以在不同的线程中执行这两个子表达式
combiner.apply(
acc(acc(identity, "one"), "two"),
acc(acc(identity, "three"), "four"));
关于你的第二个问题,我用一个简化的累加器来解释这个问题:
BiFunction<StringBuilder,String,StringBuilder> accumulator =
(builder,name) -> builder.append(name);
对于上述累加器
,情况并非如此。问题是,您正在对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);
//identity=“”
双功能累加器=字符串::concat;
//标识=null
双功能累加器=
(生成器,名称)->builder==null
? 新建StringBulder(名称):builder.append(名称);
基本正确(+1),但我想放大一个特定点
identity
参数到reduce
必须是一个identity值。如果它是一个对象就可以了,但如果是,它应该是不可变的。如果“身份”对象发生变异,它就不再是身份!有关这一点的更多讨论,请参阅相关问题
看起来这个例子源自Richard Warburton的例子5-19,Java 8 Lambdas,O'Reilly 2014。如果是这样的话,我必须和善良的沃伯顿博士谈谈这件事。谢谢你,我有一个问题,为什么每次迭代我都会收到不同的结果,我猜是为了并行化。。。为什么这几个结果使用名称代码??请看我编辑的问题。@chiperortiz:我已经更新了关于第二个问题的答案。这个例子真的源于这本书吗?在这种情况下,短语good book似乎有问题。在这本书中,是一个更复杂的示例,仅使用顺序流。我将使用双函数,但我是否应该使用相同的BinaryOperator?类似地,要reduce的BinaryOperator参数必须是关联的。否则,您将并行得到乱七八糟的结果。Richard的示例用于顺序流而不是并行流Stuart,谢谢您的回复…@chiperortiz该示例确实是顺序的,但代码顺序给出正确的结果和并行给出错误的结果是不合适的,尤其是在一本试图解释这些东西的书中。(此外,我怀疑即使是顺序代码也违反了一些限制,幸运的是它恰好给出了正确的结果。)
BiFunction<StringBuilder,String,StringBuilder> accumulator =
(builder,name) -> builder.append(name);
acc(acc(acc(identity, "one"), "two"), "three")
acc(acc(identity, "one"), acc(acc(identity, "two"), "three"))
// 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);