Как работает метод sort() для списка вместе с Comparator в Java 18
У меня есть класс родитель Animal
и его производные Dog
, Cat
, Hamster
, Pig
.
Dog
и Cat
реализуют функционал интерфейса Omnivore
(всеядный), а Pig
и Hamster
реализуют Herbivore
(травоядный). Моя задача по принадлежности к интерфейсу отсортировать животных. Придумал вот такой метод сортировки:
public static void sortList(List<Animal> pets) {
pets.sort(Comparator.comparing(pet -> pet instanceof Animal.Omnivore ? 1 : 0));
}
Но не до конца понимаю, как это работает. У меня есть догадка, что в параметре pet
каким-то образом хранится экземпляр объекта из pets
, но я не уверен, что это так. Поэтому хочу спросить: откуда он берется?) Если это так, то как он перебирает список и запихивает экземпляр в pet
?
Ответы (1 шт):
У меня есть догадка, что в параметре
pet
каким-то образом хранится экземпляр объекта изpets
, но я не уверен, что это так.
Догадка в целом верная, в параметр pet
и будет "подставляться" каждый элемент из списка pets
в процессе сортировки.
Подобная реализация сортировки работает c 2014 лет со времени выпуска Java 8 (а не Java 18) :).
Можно расписать всё по порядку:
pets.sort(Comparator.comparing(pet -> pet instanceof Animal.Omnivore ? 1 : 0));
- У экземпляра списка c животными
pets
вызывается методList::sort(Comparator<? super E> c)
(гдеE
- супер-тип для элементов списка, т.е.Animal
в данном случае), - который принимает на вход экземпляр компаратора, созданный при помощи статического фабричного метода
Comparator.comparing(Function<? super E, ? extends Comparable> keyExtractor)
, - который принимает на вход некоторую функцию, преобразующую экземпляры типа
E
(элементы нашего списка) в "сравнимые" экземпляры, т.е. реализующие интерфейсComparable
.
В данном случае эта функция описана в виде лямбды
pet -> pet instanceof Animal.Omnivore ? 1 : 0
,
которая принимает на вход экземпляры типа Animal
и приводит их к типу Integer
.
Но можно было бы ещё упростить код, убрав тернарный оператор и параметр pet
, заменив указанную лямбда-функцию с оператором instanceof
ссылкой на метод Class::isInstance
соответствующего интерфейса.
pets.sort(Comparator.comparing(Animal.Omnivore.class::isInstance));
Этот метод будет так же вызываться для каждого элемента списка и обеспечит аналогичную сортировку, так как он возвращает результат типа boolean
, который так же является Comparable
:
false < true
.
P.S. Свиньи -- всеядны (см. википедию и фильм Snatch), в отличие от морских свинок GuineaPig