Java Comparator.reversed() 不使用 lambda 编译
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25172595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparator.reversed() does not compile using lambda
提问by Andrey
I have a list with some User objects and i'm trying to sort the list, but only works using method reference, with lambda expression the compiler gives an error:
我有一个包含一些 User 对象的列表,我正在尝试对列表进行排序,但只能使用方法引用工作,使用 lambda 表达式编译器会给出错误:
List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error
Error:
错误:
com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
userList.sort(Comparator.comparing(u -> u.getName()).reversed());
^
symbol: method getName()
location: variable u of type Object
1 error
采纳答案by Stuart Marks
This is a weakness in the compiler's type inferencing mechanism. In order to infer the type of u
in the lambda, the target typefor the lambda needs to be established. This is accomplished as follows. userList.sort()
is expecting an argument of type Comparator<User>
. In the first line, Comparator.comparing()
needs to return Comparator<User>
. This implies that Comparator.comparing()
needs a Function
that takes a User
argument. Thus in the lambda on the first line, u
must be of type User
and everything works.
这是编译器类型推断机制的一个弱点。为了推断u
lambda 中的类型,需要建立lambda 的目标类型。这是如下完成的。userList.sort()
期待类型的参数Comparator<User>
。在第一行,Comparator.comparing()
需要返回Comparator<User>
。这意味着Comparator.comparing()
需要一个Function
带User
参数的。因此,在第一行的 lambda 中,u
必须是类型User
并且一切正常。
In the second and third lines, the target typing is disrupted by the presence of the call to reversed()
. I'm not entirely sure why; both the receiver and the return type of reversed()
are Comparator<T>
so it seems like the target type should be propagated back to the receiver, but it isn't. (Like I said, it's a weakness.)
在第二行和第三行中,目标输入被调用打乱了reversed()
。我不完全确定为什么;接收器和返回类型reversed()
都是Comparator<T>
如此,因此似乎目标类型应该传播回接收器,但事实并非如此。(就像我说的,这是一个弱点。)
In the second line, the method reference provides additional type information that fills this gap. This information is absent from the third line, so the compiler infers u
to be Object
(the inference fallback of last resort), which fails.
在第二行中,方法引用提供了填补这一空白的附加类型信息。第三行中没有此信息,因此编译器推断u
为Object
(最后的推理回退)失败。
Obviously if you can use a method reference, do that and it'll work. Sometimes you can't use a method reference, e.g., if you want to pass an additional parameter, so you have to use a lambda expression. In that case you'd provide an explicit parameter type in the lambda:
显然,如果您可以使用方法引用,那么就可以使用它。有时你不能使用方法引用,例如,如果你想传递一个额外的参数,那么你必须使用一个 lambda 表达式。在这种情况下,您将在 lambda 中提供显式参数类型:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
It might be possible for the compiler to be enhanced to cover this case in a future release.
在未来的版本中,可能会增强编译器以涵盖这种情况。
回答by Misha
You can work around this limitation by using the two-argument Comparator.comparing
with Comparator.reverseOrder()
as the second argument:
您可以通过使用双参数Comparator.comparing
withComparator.reverseOrder()
作为第二个参数来解决此限制:
users.sort(comparing(User::getName, reverseOrder()));