Can some one explain the difference between following variants of complex Comparator
s?
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?
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);