我正在准备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);
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都那么好..但后来令人费解的部分.在代码示例下面,他们声明您可以使用方法链接在一行中编写它.也许我误解了,但当我链接比较和thenComparing部分时,我得到一个编译错误.它与被比较的对象类型有关(首先是String,然后是int).
当我输入中间变量而不是链接时,为什么它可以工作?是否有可能连锁?
当你链接两者时,编译器无法推断返回的比较器的类型参数,comparing()因为它依赖于返回的比较器thenComparingInt()本身无法推断.
在lambda参数中指定类型comparing()(或使用方法引用),它解决了推理问题,因为comparing()可以推断出返回的类型.:
Comparator<Squirrel> c = Comparator.comparing((Squirrel s) -> s.getSpecies())
.thenComparingInt(s -> s.getWeight());
Run Code Online (Sandbox Code Playgroud)
请注意,在lambda参数中指定类型thenComparingInt()(或使用方法引用),例如:
Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies())
.thenComparingInt((Squirrel s) -> s.getWeight());
Run Code Online (Sandbox Code Playgroud)
在推理类型计算中不考虑接收器(这里是链接方法的返回类型).
这篇JDK 8教程/文档很好地解释了这一点:
注意:重要的是要注意推理算法仅使用调用参数,目标类型,并且可能使用明显的预期返回类型来推断类型.推理算法不使用程序中稍后的结果.
是的,这是可能的-链comparing(...)带thenComparing(...),并与compare(...)使用方法引用的,而不是lambda表达式:
public int compare(Squirrel s1, Squirrel s2) {
return Comparator.comparing(Squirrel::getSpecies)
.thenComparing(Squirrel::getWeight)
.compare(s1, s2);
}
Run Code Online (Sandbox Code Playgroud)
为什么这样工作?在回答类似问题时,我无法比布莱恩更好地解释它.
此外,这可以用1行重写(假设您有一个要排序的松鼠列表):
list.sort(Comparator.comparing(Squirrel::getSpecies).thenComparing(Squirrel::getWeight));
Run Code Online (Sandbox Code Playgroud)