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?
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);
Accepts a function that extracts an int sort key from a type T, and returns a Comparator that compares by that sort key.
Returns a comparator that compares Comparable objects in natural order.
You can check natural order from there; difference between natural ordering and total ordering
Comparator API; https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#naturalOrder--
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With