简体   繁体   English

Java8流并行减少BiFunction累加器

[英]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 ,它接受UT参数并返回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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM