Comparator.reversed ()는 람다를 사용하여 컴파일되지 않습니다.

일부 사용자 개체가있는 목록이 있고 목록을 정렬하려고하지만 메서드 참조를 사용하여 작동하며 람다 식을 사용하면 컴파일러에서 오류가 발생합니다.

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

오류:

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



답변

이것은 컴파일러의 유형 추론 메커니즘의 약점입니다. u람다 의 유형을 추론하려면 람다의 대상 유형 을 설정해야합니다. 이것은 다음과 같이 수행됩니다. userList.sort()유형의 인수가 필요합니다 Comparator<User>. 첫 번째 줄에서 Comparator.comparing()를 반환해야합니다 Comparator<User>. 이것은 그 의미 Comparator.comparing()필요 Function소요 User인수를. 따라서 첫 번째 줄의 람다에서 u유형이어야 User하며 모든 것이 작동합니다.

두 번째 및 세 번째 줄에서에 대한 호출의 존재로 인해 대상 입력이 중단됩니다 reversed(). 나는 그 이유를 완전히 모르겠습니다. 수신자와 반환 유형이 reversed()모두 Comparator<T>있으므로 대상 유형이 수신자에게 다시 전파되어야하는 것처럼 보이지만 그렇지 않습니다. (내가 말했듯이 약점이다.)

두 번째 줄에서 메서드 참조는이 간격을 채우는 추가 유형 정보를 제공합니다. 컴파일러를 추론이 때문에이 정보는, 세 번째 줄에서 부재 uObject실패 (최후의 추론 대체).

분명히 메서드 참조를 사용할 수 있다면 그렇게하면 작동합니다. 예를 들어 추가 매개 변수를 전달하려는 경우와 같이 메서드 참조를 사용할 수없는 경우가 있으므로 람다 식을 사용해야합니다. 이 경우 람다에 명시 적 매개 변수 유형을 제공합니다.

userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());

향후 릴리스에서이 경우를 다루기 위해 컴파일러를 향상시킬 수 있습니다.


답변

두 번째 인수로 Comparator.comparingwith 두 인수 를 사용하여이 제한을 해결할 수 있습니다 Comparator.reverseOrder().

users.sort(comparing(User::getName, reverseOrder()));


답변