![](/img/trans.png)
[英]What does actually Java stream reduce if only one of BinaryOperator argument is got summarized with itself?
[英]Java 8 reduce BinaryOperator what is used for?
我正在閱讀O'reilly
Java 8 O'reilly
是一本非常好的書。 我遇到過這樣的例子。
我有一個
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());
這產生了正確的輸出。
Mister:John Lennon,Mister:Paul Mccartney,Mister:George Harrison,Mister:Ringo Starr
我的問題是reduce
方法最后一個參數是BinaryOperator
我的問題是這個參數用於哪個? 如果我改變
.reduce(new StringBuilder(),accumulator,(left,right)->new StringBuilder());
如果我傳遞NULL
則輸出相同,則返回NPE。
這個參數用於什么?
UPDATE
為什么如果我在parallelStream
上運行它我收到不同的結果?
第一次運行。
returned StringBuilder length = 420
第二輪
returned StringBuilder length = 546
第三次運行
returned StringBuilder length = 348
等等? 為什么這個...不應該在每次迭代時返回所有值?
任何幫助都非常感激。
謝謝。
接口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
,可以將上述表達式轉換為以下表達式。 現在可以在不同的線程中執行兩個子表達式。
combiner.apply(
acc(acc(identity, "one"), "two"),
acc(acc(identity, "three"), "four"));
關於你的第二個問題,我用一個簡化的accumulator
來解釋這個問題:
BiFunction<StringBuilder,String,StringBuilder> accumulator =
(builder,name) -> builder.append(name);
根據Javadoc for Stream :: reduce , accumulator
必須是關聯的 。 在這種情況下,這意味着,以下兩個表達式返回相同的結果:
acc(acc(acc(identity, "one"), "two"), "three")
acc(acc(identity, "one"), acc(acc(identity, "two"), "three"))
對於上面的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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.