Как работает метод 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