[英]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.