【问题标题】:Why Comparator.comparing doesn't work with String::toLowerCase method reference?为什么 Comparator.comparing 不适用于 String::toLowerCase 方法参考?
【发布时间】:2014-04-08 12:26:19
【问题描述】:

我正在尝试按相反的顺序(忽略大小写)对字符串数组进行排序,而不修改它,只打印它。所以我正在使用Java8流。但我做不到。

这是我的尝试:

package experimentations.chapter02;

import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.Collectors;

public class StringStream {

    public static void main(String[] args) {
        sortStrings();
    }

    public static void sortStrings(){
        String[] stringsArray = "The quick brown fox has a dirty ladder".split("\\s+");
        System.out.println(
                Arrays.stream(stringsArray)
                .sorted(Comparator.comparing(String::toLowerCase).reversed())
                .collect(Collectors.toList())
        );
    }

}

这里的问题是String::toLowerCase在静态方法Comparator.comparing中不被接受。

同时,我设法对数组进行了排序,但修改它:

public static void sortStrings(){
        String[] stringsArray = "The quick brown fox has a dirty ladder".split("\\s+");
        System.out.println(
                Arrays.stream(stringsArray)
                .map(String::toLowerCase)
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList())
        );
}

那么,最简​​单的解决方法是什么?

【问题讨论】:

  • 我找到了解决方案: .sorted((String e) -> e.toLowerCase) 。同时,我要求删除该帖子,因为这对我来说似乎很明显,我可以在不问问题的情况下找到它...
  • 你的第一个代码 sn-p 编译得很好。您使用的是 Java 8 的旧版本吗?或者也许在eclipse中编译?您提到的问题已在 build 129 中修复。另请参阅 stackoverflow.com/q/21751830/829571

标签: java comparator java-8 java-stream method-reference


【解决方案1】:

问题是,Java 不能为一些复杂的表达式推导出泛型。第一条语句有效,而第二条语句导致编译时错误:

Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
Comparator<String> comparator = Comparator.comparing(String::toLowerCase).reversed();

有几种方法可以解决这个问题。以下是其中三个:

将中间比较器存储在一个变量中:

Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
System.out.println(
            Arrays.stream(stringsArray)
            .sorted(comparator.reversed())
            .collect(Collectors.toList()));

使用String.CASE_INSENSITIVE_ORDER:

System.out.println(
            Arrays.stream(stringsArray)
            .sorted(String.CASE_INSENSITIVE_ORDER.reversed())
            .collect(Collectors.toList()));

添加显式类型参数:

System.out.println(
            Arrays.stream(stringsArray)
            .sorted(Comparator.<String,String>comparing(String::toLowerCase).reversed())
            .collect(Collectors.toList()));

【讨论】:

  • OP发布的第一个代码sn-p编译正常。
  • @assylias:你在说哪个代码 sn-p? OP发布的第一个代码sn-p在这里没有编译。
  • Arrays.stream(stringsArray).sorted(Comparator.comparing(String::toLowerCase).reversed()).collect(Collectors.toList()) 在 b132 上使用 javac/netbeans 编译。
  • @assylias:嗯,它不能使用 Java 编译器进行编译,Java 编译器是 Oracle 最新版本 JDK8 的一部分。
  • @assylias:我不确定,为什么会出现编译错误。关于方法引用的规则非常复杂。因此,我创建了一个新问题:stackoverflow.com/questions/22945870/…
【解决方案2】:

我找到了解决方案:

 .sorted((String e) -> e.toLowerCase) 

我认为语法有问题

 .sorted(String::toLowerCase)

是编译器然后期望将一个Object传递给String的实例方法toLowerCase。所以我需要自己制作lambda方法,不要忽略lambda参数(String)的类型,否则编译器仍然无法解析。

【讨论】:

  • IntelliJ 告诉我你一开始尝试的是循环推理,这是被禁止的。现在,我试着理解什么是循环推理:)
  • assylias 告诉我,似乎某些 IDE 还没有真正支持 Java8 功能。另外,我在 Netbeans 中尝试了类似的代码,没有任何问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2013-04-10
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多