【发布时间】:2014-12-22 18:24:30
【问题描述】:
大家。
在关于减少的 Oracle 教程 (https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html) 中,我们提供了如何使用 Stream.collect() 方法的示例。任务是找到流中值的平均值。在示例中有辅助类 Averager:
class Averager implements IntConsumer
{
private int total = 0;
private int count = 0;
public double average() {
return count > 0 ? ((double) total)/count : 0;
}
public void accept(int i) { total += i; count++; }
public void combine(Averager other) {
total += other.total;
count += other.count;
}
}
然后我们有类似的东西:
Averager averageCollect = roster.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(Person::getAge)
.collect(Averager::new, Averager::accept, Averager::combine).
所以我们建议使用该辅助类的三个方法引用。由于 Stream.collect 签名是:
collect(供应商供应商,BiConsumer 累加器,BiConsumer 组合器)
,其中 BiConsumer - 具有功能方法 accept(Object, Object) 的功能接口。
问题是我们如何使用 Avereager::accept (signature void accept(int i) - 一个参数,不返回值) 代替 collect() 的第二个参数 - 这是一个函数,它不返回值但接受两个参数。 如果我们深入研究所有这些库调用,我们会发现输入 lambda 的一些转换会导致适当地调用 accept(a, b) - 带有两个参数,但是编译器最初如何识别它是正确的?
我们可以这样重写 collect() 调用:
...collect(() -> new Averager(), (a, i) -> a.accept(i), Averager::combine),
使用 lambdas 而不是方法引用,但我仍然不明白第二个 lambda 可以有一个参数,而它应该是两个。
提前谢谢你。
【问题讨论】: