【问题标题】:Comparator.comparing() function returns different results with lambdas and method reference [duplicate]Comparator.comparing() 函数使用 lambdas 和方法引用返回不同的结果
【发布时间】:2020-11-08 13:25:57
【问题描述】:

我正在尝试使用 Comparator.comparing 函数根据字符串的长度对字符串数组进行排序。所以,我有以下代码:

String[] arr = new String[]{"Hello","I","Am","Learning","Java"};
  1. 当我尝试按长度递减顺序对其进行排序时,我使用方法参考得到了预期的结果,但它使用 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
  1. 但是当我按长度递增的顺序对其进行排序时,它们都会产生预期的结果:
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


【解决方案1】:

您在通用比较器 s->s.length() 上调用通用方法 reversed(),因此当时比较器与字符串无关,因此找不到 .length()(对象没有长度方法)

您可以将s 定义为字符串:

Arrays.sort(arr, Comparator.comparing((String s)->s.length()).reversed());

【讨论】:

    猜你喜欢
    • 2019-12-23
    • 2022-01-16
    • 2011-12-09
    • 2016-07-31
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    相关资源
    最近更新 更多