【发布时间】:2020-11-08 13:25:57
【问题描述】:
我正在尝试使用 Comparator.comparing 函数根据字符串的长度对字符串数组进行排序。所以,我有以下代码:
String[] arr = new String[]{"Hello","I","Am","Learning","Java"};
- 当我尝试按长度递减顺序对其进行排序时,我使用方法参考得到了预期的结果,但它使用 lambda 给出了编译时间错误 (CTE),即
Cannot resolve method length():
Arrays.sort(arr, Comparator.comparing(String::length).reversed()); //Using method reference Arrays.sort(arr, Comparator.comparing(s->s.length()).reversed()); //Using Lambda CTE
- 但是当我按长度递增的顺序对其进行排序时,它们都会产生预期的结果:
Arrays.sort(arr, Comparator.comparing(String::length)); //Using method reference Arrays.sort(arr, Comparator.comparing(s->s.length())); //Using Lambda
那么,为什么 IntelliJ 在使用 lambdas 的第一个场景中抛出 CTE,而在涉及单个方法调用的场景中方法引用可以替换 lambdas,所以理想情况下它们应该表现相同?
另外,为什么上面描述的 CTE 需要替换为
Comparator.comparing((String s) -> s.length()).reversed()
【问题讨论】:
-
这里的问题不在于 lambda 的含义与方法引用不同,而是您的程序中没有足够的类型信息来解析 lambda。 (本质上,我们已经被类型推断宠坏了;我们习惯于将重要信息留在程序之外并让编译器弄清楚,而不是当我们向编译器询问太多时,我们认为我们是合理的.) 您在另一个泛型方法中将隐式 lambda 与链式泛型方法结合在一起。你要求编译器读懂你的想法!
-
解决方案,正如相关答案所说,是提供更多类型信息,或者使用显式 lambda,一个精确的方法引用,为 lambda (
Comparator<String>) 提供目标类型,打破方法调用链(将比较器拉到自己的变量中),或为comparing调用提供显式类型见证。
标签: java lambda java-8 comparator method-reference