我正在学习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装箱),此处的方法参考适用。

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

08-18 09:28