我正在尝试使用Java8按姓名和年龄对
List
员工进行排序Comparator
,我在下面创建了Comparator
,但它给了我一个编译器错误
Type mismatch: cannot convert from Comparator<Object> to <unknown>
Comparator<String> c = Comparator.comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); //compile error
但如果我明确指定类型,它就会起作用
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); //works
或者通过创建两个
Compartor
和链
Comparator<String> name = Comparator.comparing(s -> s.split("\\s+")[0]);
Comparator<String> age = Comparator.comparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
Comparator<String> cc = name.thenComparing(age); //works
我已经在左侧指定了类型
Comparator<String>
,但为什么自动类型推断没有找到正确的类型并期望显式指定。
有人可以澄清一下吗?
这是代码
String[] arr = { "alan 25", "mario 30", "alan 19", "mario 25" };
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
List<String> sorted = Arrays.stream(arr).sorted(c).collect(Collectors.toList());
System.out.println(sorted);
输出
[alan 19, alan 25, mario 25, mario 30]
Java需要知道所有变量的类型。在许多 lambda 中,它可以推断类型,但在第一个代码片段中,它无法猜测
s
的类型。我认为解决该问题的标准方法是明确声明它:
Comparator<String> c = Comparator.comparing((String s) -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
如果您查看这个答案,它在参数中具有与
Comparator.comparing()
类似的类型声明。
您的方法显式给出了
comparing()
的类型参数,显然也有效(Comparator.<String, String>comparing(…)
)。类型参数也称为类型见证。
对于声明两个比较器的另一种方法,我非常有信心在这种情况下 Java 可以从赋值左侧的
String
进行推断,就像传统的 List <String> = new ArrayList<>();
一样。当您继续在同一表达式中调用 thenComparing()
时,Java 无法再看到左侧的类型是相关的。有点像 int size = new ArrayList<>().size();
这也有效:
Comparator<String> name = Comparator.comparing(s -> s.split("\\s+")[0]);
Comparator<String> c = name.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));