Использование BiFunction вместо компаратора не работает - PullRequest
3 голосов
/ 12 апреля 2019

При инициализации коллекций, таких как TreeMap, TreeSet и т. Д. Мы можем добавить наш собственный компаратор.Код выглядит примерно так:

Map<Integer, String> map1 = new TreeMap<>(new Comparator<Integer>() {
    public int compare(Integer x, Integer y) {
        return x-y;
    }
});

Теперь мы можем заменить анонимную реализацию лямбда-выражением.Код будет выглядеть так:

Map<Integer, String> map2 = new TreeMap<>((x,y) -> x-y);

Java-8 позволяет хранить лямбда-выражения в переменной через функциональные интерфейсы .Поэтому я изменил приведенный выше код следующим образом:

BiFunction<Integer, Integer, Integer> myComparator = (x,y) -> x-y;
Map<Integer, String> map3 = new TreeMap<>(myComparator);

Но эта последняя попытка не сработала!Он выдал следующую ошибку:

Невозможно определить аргументы типа для TreeMap <>

Почему не удалось разрешить типы в последнем примере?

Примечание. Чтобы подтвердить, что это не ошибка IDE, я выполнил необработанную компиляцию, используя javac, и она все еще выдавала ту же ошибку.

Ответы [ 3 ]

7 голосов
/ 12 апреля 2019

Хотя лямбда-выражение выглядит одинаково, BiFunction не является Comparator, поэтому вы не можете их поменять местами.

Comparator<Integer> comparator = (x,y) -> x - y;
Map<Integer, String> map3 = new TreeMap<>(comparator);

Давайте углубимся в эти интерфейсы и реализуем их с помощью анонимного класса:

Comparator<Integer> comparator = new Comparator<Integer>() {
    @Override
    public int compare(Integer x, Integer y) {
        return x - y;
    }
};

BiFunction<Integer, Integer, Integer> biFun = new BiFunction<Integer, Integer, Integer>() {
    @Override
    public Integer apply(final Integer x, final Integer y) {
        return x - y;
    }
};

Разница также в названии метода. TreeMap ожидает Comparator в своем конструкторе, поскольку его внутренняя реализация вызовет compare в соответствии с контрактом с Comparator.

Кстати, BinaryOperator<T> приводит к тому же самому лямбда-выражению.

1 голос
/ 12 апреля 2019

Это просто потому, что конструктор TreeMap ожидает Comparator<Integer>, а не BiFunction.

При написании BiFunction<Integer, Integer, Integer> myComparator = ... вы явно говорите компилятору, что переменная относится к этому типу. Это предотвращает вывод компилятором типа, необходимого для конструктора TreeMap. Поскольку BiFunction не является ни Comparator, ни его подклассом, компилятор не допускает этого.

0 голосов
/ 12 апреля 2019

Потому что он ожидает, что Компаратор и вы предоставили BiFunction.Из Oracle Docs:

@FunctionalInterface
public interface Comparator<T>

Функция сравнения, которая накладывает полное упорядочение на некоторую коллекцию объектов.Компараторы могут быть переданы в метод сортировки (например, Collections.sort или Arrays.sort), чтобы обеспечить точный контроль над порядком сортировки.Компараторы также можно использовать для управления порядком определенных структур данных (таких как отсортированные наборы или отсортированные карты) или для обеспечения порядка для коллекций объектов, которые не имеют естественного порядка.

...