[英]Java8 stream parallel reduce BiFunction accumulator
i have a learning java 8 the most difficult thing i have to face is the Parallel reduction.
我正在学习Java 8,我必须面对的最困难的事情是
Parallel reduction.
here is the code from a example of the user @Stuart Marks i am studying with. 这是我正在研究的用户@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);
}
the call 电话
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());
}
this produce the right results but later i checked the signature of the reduce method 这会产生正确的结果,但后来我检查了reduce方法的签名
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
i would understand clear if the code would be something like 我会明白,如果代码将是类似的东西
.reduce(new ImmutableAverager(),(a,b)->a.accept(b),(a,b)->a.combine(b))
i dont understand how 我不明白
ImmutableAverager::accept
can convert into a BiFunction
可以转换成
BiFunction
my understanding is.. 我的理解是
this 这个
ImmutableAverager::accept
is convert it in something like 将其转换为
(ImmutableAverage a)->a.accept();//but this is a function with 1 parameter not with 2 parameters.
and 和
ImmutableAverager::merge
can convert into a BinaryOperator
my friend @Stuart Marks says 可以转换成
BinaryOperator
我的朋友@Stuart Marks说
the methods match the function arguments to reduce so we can use method references. 方法与函数参数匹配以减少约数,因此我们可以使用方法引用。
sorry if the question is simple but any help is hugely appreciate.. 很抱歉,如果问题很简单,但任何帮助将不胜感激。
best regards from Venezuela 委内瑞拉的最诚挚问候
Yes, there's a subtlety here regarding the way that arguments are shifted when this kind of method reference is used, specifically an "unbound" method reference. 是的,在使用这种方法引用(特别是“未绑定”方法引用)时,如何对参数进行移位有一个微妙的地方。
Let's look at the second argument of reduce()
. 让我们看一下
reduce()
的第二个参数。 It wants 它想要
BiFunction<U, ? super T, U> accumulator
and so the signature of its abstract method is: 因此,其抽象方法的签名为:
U apply(U, T)
(wildcard elided for brevity). (为简洁起见,省略了通配符)。 The example had used a method reference
ImmutableAverager::accept
and its signature is: 该示例使用了一个方法引用
ImmutableAverager::accept
,其签名为:
ImmutableAverager accept(int i)
It looks like this doesn't work, because a BiFunction
requires two arguments, whereas the accept
method takes only one. 看来这行不通,因为
BiFunction
需要两个参数,而accept
方法仅需要一个参数。 But notice that the accept
method is an instance method on the ImmutableAverager
class, so it implicitly also takes a "receiver", that is, the object upon which this method is called. 但是请注意,
accept
方法是ImmutableAverager
类的实例方法 ,因此它隐式还带有一个“接收器”,即在其上调用此方法的对象。 An ordinary call to this method might look like this: 对该方法的普通调用可能如下所示:
newAverager = oldAverager.accept(i);
So really, the accept
method actually takes two arguments even though it doesn't look like it. 因此,实际上,
accept
方法实际上看起来有两个参数,即使它看起来不是这样。 The first is the receiver, which is of type ImmutableAverager
, and the second is of type int
. 第一个是接收器,它是
ImmutableAverager
类型,第二个是int
类型。 The method call syntax makes it look like there's something special about the receiver, but there really isn't. 方法调用语法使接收器看起来有些特殊,但实际上没有。 It's as if this were a static method called like this:
好像这是一个像这样的静态方法:
newAverager = accept(oldAverager, i);
Now let's look at how this works with the reduce
call. 现在让我们看一下这与
reduce
调用如何工作。 The code in question is, 有问题的代码是,
reduce(..., ImmutableAverager::accept, ...)
I'm only showing the second argument here. 我只在这里显示第二个参数。 This needs to be a
BiFunction
that takes arguments of U
and T
and returns a U
as shown above. 这需要是一个
BiFunction
,它接受U
和T
参数并返回U
如上所示。 If you look at the accept
method and treat the receiver not as something special but as an ordinary argument, it takes an argument of type ImmutableAverager
and an argument of type int
, and returns an ImmutableAverager
. 如果您查看
accept
方法,并且将接收方视为特殊参数而不是特殊参数,则它将接受ImmutableAverager
类型的参数和int
类型的参数,并返回ImmutableAverager
。 So U
is inferred to be ImmutableAverager
and T
is inferred to be Integer
(boxed from int
), and the method reference here works. 因此,将
U
推断为ImmutableAverager
,将T
推断为Integer
(从int
装箱),此处的方法参考适用。
The key point is, for an unbound method reference, the method reference is to an instance method but the method is specified using the class name instead of an actual instance. 对于未绑定的方法引用,关键点是方法引用是针对实例方法的,但是该方法是使用类名而不是实际实例指定的。 When this occurs, the receiver turns into the first argument of the method call.
发生这种情况时,接收方将变成方法调用的第一个参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.