簡體   English   中英

Java 8減少BinaryOperator用於什么?

[英]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 :: reduceaccumulator必須是關聯的 在這種情況下,這意味着,以下兩個表達式返回相同的結果:

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);

nosid的答案大部分是正確的(+1),但我想擴大一個特定點。

reduceidentity參數必須是標識 沒關系,如果它是一個對象,但如果它是,它應該是不可變的。 如果“身份”對象發生變異,則不再是身份! 有關這一點的更多討論,請參閱對相關問題的回答。

看起來這個例子起源於Richard Warburton的例子5-19, Java 8 Lambdas ,O'Reilly 2014.如果是這樣,我將不得不與沃伯頓博士談談這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM