![](/img/trans.png)
[英]Why is the accumulator in Stream::reduce a BiFunction and not a BinaryOperator like the combiner?
[英]Java8 stream parallel reduce BiFunction accumulator
我正在學習Java 8,我必須面對的最困難的事情是Parallel reduction.
這是我正在研究的用戶@Stuart Marks的示例代碼。
class ImmutableAverager
{
private final int total;
private final int count;
public ImmutableAverager(){this.total = 0;this.count = 0;}
public ImmutableAverager(int total, int count)
{
this.total = total;
this.count = count;
}
public double average(){return count > 0 ? ((double) total) / count : 0;}
public ImmutableAverager accept(final int i)
{
return new ImmutableAverager(total + i, count + 1);
}
public ImmutableAverager combine(final ImmutableAverager other)
{
return new ImmutableAverager(total + other.total, count + other.count);
}
電話
public static void main(String[] args)
{
System.out.println(Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.parallel()
.reduce(new ImmutableAverager(),
ImmutableAverager::accept,
ImmutableAverager::combine)
.average());
}
這會產生正確的結果,但后來我檢查了reduce方法的簽名
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
我會明白,如果代碼將是類似的東西
.reduce(new ImmutableAverager(),(a,b)->a.accept(b),(a,b)->a.combine(b))
我不明白
ImmutableAverager::accept
可以轉換成BiFunction
我的理解是
這個
ImmutableAverager::accept
將其轉換為
(ImmutableAverage a)->a.accept();//but this is a function with 1 parameter not with 2 parameters.
和
ImmutableAverager::merge
可以轉換成BinaryOperator
我的朋友@Stuart Marks說
方法與函數參數匹配以減少約數,因此我們可以使用方法引用。
很抱歉,如果問題很簡單,但任何幫助將不勝感激。
委內瑞拉的最誠摯問候
是的,在使用這種方法引用(特別是“未綁定”方法引用)時,如何對參數進行移位有一個微妙的地方。
讓我們看一下reduce()
的第二個參數。 它想要
BiFunction<U, ? super T, U> accumulator
因此,其抽象方法的簽名為:
U apply(U, T)
(為簡潔起見,省略了通配符)。 該示例使用了一個方法引用ImmutableAverager::accept
,其簽名為:
ImmutableAverager accept(int i)
看來這行不通,因為BiFunction
需要兩個參數,而accept
方法僅需要一個參數。 但是請注意, accept
方法是ImmutableAverager
類的實例方法 ,因此它隱式還帶有一個“接收器”,即在其上調用此方法的對象。 對該方法的普通調用可能如下所示:
newAverager = oldAverager.accept(i);
因此,實際上, accept
方法實際上看起來有兩個參數,即使它看起來不是這樣。 第一個是接收器,它是ImmutableAverager
類型,第二個是int
類型。 方法調用語法使接收器看起來有些特殊,但實際上沒有。 好像這是一個像這樣的靜態方法:
newAverager = accept(oldAverager, i);
現在讓我們看一下這與reduce
調用如何工作。 有問題的代碼是,
reduce(..., ImmutableAverager::accept, ...)
我只在這里顯示第二個參數。 這需要是一個BiFunction
,它接受U
和T
參數並返回U
如上所示。 如果您查看accept
方法,並且將接收方視為特殊參數而不是特殊參數,則它將接受ImmutableAverager
類型的參數和int
類型的參數,並返回ImmutableAverager
。 因此,將U
推斷為ImmutableAverager
,將T
推斷為Integer
(從int
裝箱),此處的方法參考適用。
對於未綁定的方法引用,關鍵點是方法引用是針對實例方法的,但是該方法是使用類名而不是實際實例指定的。 發生這種情況時,接收方將變成方法調用的第一個參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.