繁体   English   中英

Java8流并行减少BiFunction累加器

[英]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 ,它接受UT参数并返回U如上所示。 如果您查看accept方法,并且将接收方视为特殊参数而不是特殊参数,则它将接受ImmutableAverager类型的参数和int类型的参数,并返回ImmutableAverager 因此,将U推断为ImmutableAverager ,将T推断为Integer (从int装箱),此处的方法参考适用。

对于未绑定的方法引用,关键点是方法引用是针对实例方法的,但是该方法是使用类名而不是实际实例指定的。 发生这种情况时,接收方将变成方法调用的第一个参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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