Java, почему коллекции.sort() по-прежнему работает с аргументом, типизированным без компаратора?



Я знаю, что в классе Java Collections есть статический метод sort:



sort(List<T> list, Comparator<? super T> c**)


Вторым аргументом в сортировке должен быть объект, реализующий интерфейсComparator и его метод сравнения.



Но когда я изучаю ссылку на метод лямбды , я вижу следующий пример:



public class Test 
{
public static void main(String[] args)
{
new Test().sortWord();
}

public void sortWord()
{
List<String> lst = new ArrayList<>();
lst.add("hello");
lst.add("world");
lst.add("apple");
lst.add("zipcode");

Collections.sort(lst, this::compareWord);

System.out.println(lst);
}

public int compareWord(String a, String b)
{
return a.compareTo(b);
}


}



Это пример ссылки на метод для примера метода.
метод compareWord не имеет ничего общего с интерфейсом Comparator, я не могу понять, почему это работает? кто-нибудь может это объяснить?



Большое вам спасибо.

731   3  

3 ответов:

int compareWord(String a, String b) имеет ту же сигнатуру, что и Метод int compare(String o1, String o2) интерфейса Comparator<String>. Поэтому он может быть использован в качестве реализации этого интерфейса.

Это более короткий способ написания:

Collections.sort(lst, new Comparator<String> () {
                     public int compare (String o1, String o2) {
                         return compareWord(o1,o2);
                     }
                 });

В Java 8 любой функциональный интерфейс, такой как Comparator (т. е. интерфейс, имеющий один абстрактный метод), может быть реализован с помощью ссылки на метод метода, имеющего сигнатуру, соответствующую сигнатуре абстрактного метода этого интерфейса.

Здесь не нужно писать явный строковый компаратор.

Просто делайте следующее, И это должно работать нормально.

Collections.sort(lst);

Кстати @Eran объяснил, тот же метод подписи о compareWord и compare в ваших сценариях.

Comparator интерфейс-это @FunctionalInterface:

Функциональный интерфейс-это интерфейс, который [...] представляет собой контракт одной функции. [...]

Для интерфейса I пусть M-набор абстрактных методов, являющихся членами I, которые не имеют той же сигнатуры, что и любой открытый метод экземпляра объекта класса. Тогда I является функциональным интерфейсом, если существует метод m в M, для которого верно оба из следующих условий:

  • Тот самый подпись м. подподписью (§8.4.2) подписи каждого метода в М.

  • M является заменяемым типом возврата (§8.4.5) для каждого метода в M.

В дополнение к обычному процессу создания экземпляра интерфейса путем объявления и создания экземпляра класса (§15.9), экземпляры функциональных интерфейсов могут быть созданы с помощью ссылочных выражений метода и лямбда-выражений (§15.13, §15.27).

Это дальше упоминает Comparator в качестве примера:

Определение функционального интерфейса исключает методы в интерфейсе, которые также являются открытыми методами в объекте. Это должно позволить функциональную обработку интерфейса, такого как java.утиль.Компаратор, объявляющий множество абстрактных методов,из которых только один действительно "новый" - int compare(T, T). Другой метод-boolean equals (Object) - является явным объявлением абстрактного метода, который в противном случае был бы неявно объявлен и будет автоматически реализуется каждым классом, реализующим интерфейс.

Помимо анонимного примера класса, предоставленного @Eran, и ссылочного выражения метода из вопроса, также будет работать выражение lamba:

Collections.sort(lst, (a, b) -> ...);

Comments

    Ничего не найдено.