方法链如何在Java 8 Comparator中工作?

时间:2018-03-24 20:36:29

标签: java java-8 ocpjp

我正在准备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);
    }
}

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

为什么当我输入一个中间变量而不是链接时它可以工作?是否可以连锁?

2 个答案:

答案 0 :(得分:8)

当你链接两者时,编译器无法推断返回的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非常清楚地解释道:

  

注意:请务必注意推理算法仅使用   调用参数,目标类型,可能是一个明显的预期   返回类型以推断类型。推理算法不使用   该计划后期的结果。

答案 1 :(得分:5)

是的,有可能 - 链thenComparing(...)compare(...)public int compare(Squirrel s1, Squirrel s2) { return Comparator.comparing(Squirrel::getSpecies) .thenComparing(Squirrel::getWeight) .compare(s1, s2); } 使用方法引用而不是lambda表达式:

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

为什么这样工作?我无法在他的answer中向Brian({3}}更好地解释它。

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

let spanNumber = document.querySelector('.number1')

let number = spanNumber.textContent

let newNumber = number.split('.').join(',')

spanNumber.innerHTML = newNumber