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