【问题标题】:How does method chaining work in Java 8 Comparator? [duplicate]Java 8 Comparator 中的方法链是如何工作的? [复制]
【发布时间】:2018-03-24 20:36:28
【问题描述】:

我正在为 Java 8 证书做准备,以下让我有点困惑,也许有人可以帮助我解决这个问题? 在示例中,对 Squirrel 类进行了建模。它有名字和重量。现在您可以创建一个 Comparator 类来使用这两个字段对这个东西进行排序。所以首先按名称排序,然后按重量排序。像这样的:

public class ChainingComparator implements Comparator<Squirrel> {
    public int compare(Squirrel s1, Squirrel s2) {

        Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies());
        c = c.thenComparingInt(s -> s.getWeight());

        return c.compare(s1, s2);
    }
}

到目前为止一切顺利.. 但令人费解的部分。在代码示例下方,他们声明您可以使用方法链接将其编写在一行中。也许我误解了,但是当我链接 comparingthenComparing 部分时,我得到一个编译错误。这与比较的对象类型有关(首先是 String,然后是 int)。

为什么当我放入一个中间变量而不是链接时它会起作用?是否有可能完全链接?

【问题讨论】:

  • 试试这个 ` Comparator c = Comparator.comparing((Squirrel s) -> s.getSpecies()).thenComparingInt(s -> s.getWeight());`跨度>

标签: java java-8 ocpjp


【解决方案1】:

当你链接两者时,编译器无法推断comparing()返回的比较器的类型参数,因为它依赖于自身无法推断的thenComparingInt()返回的比较器。

comparing() 的 lambda 参数中指定类型(或使用方法引用),它解决了推断问题,因为可以推断出 comparing() 的返回类型。 :

    Comparator<Squirrel> c = Comparator.comparing((Squirrel s)  -> s.getSpecies())
                                       .thenComparingInt(s -> s.getWeight());

注意在thenComparingInt()的lambda参数中指定类型(或使用方法引用)如:

    Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies())
                                       .thenComparingInt((Squirrel s) -> s.getWeight());

将不起作用,因为在推理类型计算中不考虑接收者(这里是链接方法的返回类型)。

This JDK 8 tutorial/documentation 解释得很好:

注意:需要注意的是,推理算法仅使用 调用参数、目标类型,可能还有一个明显的预期 返回类型以推断类型。推理算法不使用 程序后面的结果。

【讨论】:

    【解决方案2】:

    是的,有可能 - 使用方法引用而不是 lambda 表达式将 comparing(...)thenComparing(...)compare(...) 链接起来:

    public int compare(Squirrel s1, Squirrel s2) {
        return Comparator.comparing(Squirrel::getSpecies)
            .thenComparing(Squirrel::getWeight)
            .compare(s1, s2);
    }
    

    为什么会这样?我无法比 Brian 在他的 answer 中更好地解释它与类似的 question

    此外,这可以用 1 行重写(假设您有一个要排序的松鼠列表):

    list.sort(Comparator.comparing(Squirrel::getSpecies).thenComparing(Squirrel::getWeight));
    

    【讨论】:

      猜你喜欢
      • 2019-09-22
      • 1970-01-01
      • 1970-01-01
      • 2017-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多