Method Reference works for Comparator.comparing method whereas a lambda expression isn't working

Viewed 95

Can anyone please help me understand why does the below method reference works with thenComparing method:

List<Person> li = personList.stream()
                .sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getName))
                .collect(Collectors.toList());

But when I am trying to do it using a lambda expression, it doesn't work. Here, I am getting a compilation error - "Cannot resolve method getAge in 'Object'" :

List<Person> li = personList.stream()
                .sorted(Comparator.comparing(person -> person.getAge()).thenComparing(person -> person.getName()))
                .collect(Collectors.toList());

Moreover, I can see that if I remove the thenComparing method, then this code again works with lambda expression:

List<Person> li = personList.stream()
                .sorted(Comparator.comparing(person -> person.getAge()))
                .collect(Collectors.toList());

Can you please let me know where I am going wrong?

1 Answers

The problem is with this expression:

Comparator.comparing(person -> person.getAge()).thenComparing(person -> person.getName())

In the first part Comparator.comparing(person -> person.getAge()), the compiler is not able to infer the type of the lambda argument as Person, because the expression is not assigned to a variable that helps infer that information.

On the other hand, when removing the thenComparing() part, the compiler can infer the type of the lambda argument, because the comparator Comparator.comparing(person -> person.getAge()) is targeted as argument to the sorted() method, which is being invoked on a Stream<Person>.

Note that if you explicitly specify the type of the argument, it works:

Comparator.comparing((Person person) -> person.getAge()).thenComparing(person -> person.getName())
Related