Java Lambda для преобразования компаратора - промежуточное представление

Я пытаюсь понять, как работает функция Comparator.comparing. Я создал свой собственный метод сравнения, чтобы понять его.

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;
}

Последняя строка в этой функции генерирует исключение.

Однако, если я изменю эту функцию на

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));
}

Он работает нормально, как и ожидалось.

Каков промежуточный функциональный интерфейс, который использует вторая попытка, которая может преобразовать лямбда в Comparator?

Ответ 1

Каков промежуточный функциональный интерфейс, который использует вторая попытка, которая может преобразовать лямбду в Компаратор?

Сам Comparator.

Внутри второго метода вы определили Comparator, а не промежуточный объект, который был добавлен в Comparator.

Последняя строка в этой функции генерирует исключение.

Да, это должно быть.

Если два класса являются функциональными интерфейсами и имеют похожие методы (с идентичными сигнатурами и одинаковым типом возврата), это не означает, что они могут использоваться взаимозаменяемо.


Интересный трюк - вы можете сделать Comparator<T>, обратившись к методу BiFunction<T, T, Integer> bfun apply:

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
    final BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
    return bfun::apply; // (a, b) -> bfun.apply(a, b);
}

Ответ 2

Промежуточный функциональный интерфейс во второй попытке - просто Comparator<T>:

Это можно увидеть, потому что ваш фрагмент кода эквивалентен следующему:

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
    Comparator<T> comparator = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
    return comparator;
}