【问题标题】:Java stream.collect() lambda arguments typesJava stream.collect() lambda 参数类型
【发布时间】: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 可以有一个参数,而它应该是两个。

提前谢谢你。

【问题讨论】:

    标签: java reduction


    【解决方案1】:

    我认为混淆在于您可以执行以下操作:

    Averager avg = new Averager();
    BiConsumer<Averager, Integer> consumer = Averager::accept;
    consumer.accept(avg, 17);
    

    虽然Averager::accept 有一个签名说它接受一个参数(int i),但它可以被视为一个接受两个参数的BiConsumer&lt;Averager, Integer&gt;:一个被调用者(一个“this”)和一个论据(int i)。

    延伸阅读:The Java™ Tutorials: Method References

    【讨论】:

    • 确实如此。所有这些问题描述都可以缩短为一行代码:BiConsumer consumer = Averager::accept;非常棘手的语法和直观我理解。在 The Java™ Tutorials: Method References 中的例子更清楚: compare() 方法有两个参数,所以我们可以使用 Person::CompareByAge(也有两个参数)。但在前面的例子中,第一个参数以某种方式推导出来。
    • 是的。 :-) 好问题。满意请采纳。
    • 很遗憾,我没有任何好的资源。在这样的场景中,可能有很多关于类型系统和类型推断的材料。
    • 刚刚找到这个早午餐:stackoverflow.com/questions/26862874/…
    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多