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, я не могу понять, почему это работает? кто-нибудь может это объяснить?
Большое вам спасибо.
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