I'm trying to make sense of how Comparator.comparing function works. I created my own comparing method to understand it.
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
return (Comparator<T>) bfun;
}
The last line in this function throws an exception.
However, if I change this function to
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
return (T a, T b) -> f.apply(a).compareTo(f.apply(b));
}
It works just fine as expected.
What is the intermediate functional interface which the second attempt uses, which is able to convert the lambda to Comparator?
BiFunctionbecause that's the type of the variable it's assigned to. In the second example the lambda must convert to aComparatorbecause that's the return type of the method.BiFunctionandComparatorhave the same "shape", so the same lambda can become either depending on context, but they are different types so casting one to another will fail.