Complex Comparators in java 8

Oleh Kurpiak :

Can some one explain the difference between following variants of complex Comparators?

List<String> listOfStrings = Arrays.asList("algo", "test", "is", "a", "common");

listOfStrings.stream()
             .sorted(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
             .sorted(Comparator.naturalOrder().thenComparing(Comparator.comparingInt(String::length))
             .forEach(System.out::println);

Why first call of sorted is OK, while second one can not even compile?

Eran :

The compiler knows that Comparator.comparingInt(String::length) returns a Comparator<String> (since you are passing a ToIntFunction<String> to it), and therefore expects the second Comparator, passed to thenComparing, to be a Comparator<String>, so it can infer the type of the Comparator returned by Comparator.naturalOrder() to be a Comparator<String>.

On the other hand, when the first Comparator is returned by Comparator.naturalOrder() (which returns a Comparator<T>), the compiler doesn't know which type of Comparator to expect for the argument of thenComparing, so it rejects the Comparator<String> passed to it.

This error can be avoided if you declare the type of the Comparator returned by Comparator.naturalOrder() explicitly:

Comparator<String> comp = Comparator.naturalOrder();
listOfStrings.stream()
             .sorted(comp.thenComparing(Comparator.comparingInt(String::length)))
             .forEach(System.out::println);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=114610&siteId=1