Интерфейсы Comparable и Comparator в Java

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr

Данная статья:


Привет! Это статья про интерфейсы Comparable и Comparator. Для понимания материала Вам, естественно, нужно знать что такое интерфейс.

Что такое Comparable и Comparator в Java

В своей работе программисты часто сталкиваются с тем, что надо что-то сортировать - например, покупая товары в интернет-магазине Вы можете сортировать их по цене, популярности и т.д.

Но для того, чтобы что-то отсортировать, нам нужно сравнивать объекты по каким-то правилам. Тут, казалось бы, все просто - мы можем сортировать числа, да и в сортировке по алфавиту нет ничего сложного. Да, с такими данными все легко. Но как нам сравнить два объекта класса Car? По цене, пробегу, лошадиным силам или дате выпуска? А может по количеству владельцев?

Если у нас есть два объекта класса Cat - как сравнить их? По кличке? По породе? По возрасту?

Как видите, не всегда очевидно как именно можно сравнить два объекта. Но не беда - мы сами можем прописать эти правила. Именно для этого мы можем реализовать интерфейсы Comparable и Comparator.

  • Кроме того, некоторые встроенные возможности в Java можно использовать только, если Ваш класс реализует Comparable или Comparator.

Интерфейс Comparable

С английского "Comparable" переводится как "сравнимый". Имплементируя этот интерфейс мы как бы говорим "Эй, теперь объекты этого класса можно сравнивать между собой! И я знаю, как это сделать!" А до этого было нельзя 🙂

Так как выглядит интерфейс Comparable? Очень просто - в нем находится всего один метод:

Как видите, если мы реализуем этот интерфейс нам придется определить только один метод - compareTo(T o). С английского "compareTo" переводится как "сравнить с". Именно этот метод буде использоваться во всяких сортировках.

Вы могли заметить, что метод compareTo(T o) возвращает int. Он возвращает:

  •  ноль, если два объекта равны;
  • число >0, если первый объект (на котором вызывается метод) больше, чем второй (который передается в качестве параметра);
  • число <0, если первый объект меньше второго.

Давайте посмотрим на примере. Представим, что мы хотим сравнить два дома.

Давайте у нас будет класс House:

Как Вы можете видеть, у нас есть четыре параметра - размер дома, цена, город, в котором дом находится, и boolean "hasFurniture" ("продается ли дом с мебелью"). Мы НЕ сделали эти переменные приватными чтобы не отягощать код и не писать гетеры и сеттеры на каждый параметр - но Вы для практики можете это сделать 🙂 Давайте просто добавим конструктор и метод "вывести все параметры":

Отлично! Но пока мы не можем сравнить два объекта типа House. Например, если мы попробуем создать TreeSet из объектов типа HouseTreeSet всегда сортирует свои элементы. О TreeSet можете почитать в нашей статье о коллекциях) и добавить туда элемент:

получим ошибку:

Как мы уже говорили, TreeSet сортирует свои элементы - но в данном случае сортировать у него не получится, поскольку он не знает, по какому критерию нужно сортировать 🙁

Теперь, давайте имплементируем  Comparable:

Как видите, мы решили сортировать дома по площади.

Теперь давайте создадим три объекта House и положим их в TreeSet:

На экране получим:

Как видите, наши дома стоят не в порядке добавления (Токио, Оксфорд, Париж), а отсортированы по площади (Оксфорд, Париж, Токио). Ну, и ошибок, естественно, тоже нет.

Кстати, метод compareTo(T o), который требует реализовать интерфейс Comparable, часто называют "естественным сравнением" ("natural comparison method") - т.е. методом по умолчанию. Основные типы (например, Integer, String, Float) уже имеют свои методы compareTo(T o).

Тем не менее, если Вам нужен "нестандартный" вид сортировки - следует использовать Comparator.

Интерфейс Comparator

Итак, нестандартная сортировка. Допустим, мы все согласны что логичнее всего сравнивать дома по площади. Ну а если их нужно отсортировать, например, по цене?

Для этой цели мы можем создать отдельный класс, который реализует интерфейс Comparator.

Например, у нас уже есть класс House. Давайте создадим отдельный класс, которые будут выполнять функцию сравнения - PriceComparator:

Обратите внимение: мы указываем тип объектов, которые хотим сравнивать (House) в скобках после слова "Comparator".

Теперь давайте возьмем main из предыдущего примера, только поместим наши объекты не в TreeSet, а в ArrayList:

Если запустить этот код, то мы увидим, что все наши элементы лежат в порядке добавление - т.е. они не отсортированы.

Теперь давайте создадим объект класса PriceComparator, а потом вызовем у нашего ArrayList метод sort(), который принимает на вход как раз объект класса, реализующего интерфейс Comparator, в нашем  PriceComparator-а отсортируем наш ArrayList:

В консоли получим:

Ура! Наши дома отсортированы по цене. Теперь Вы знаете как использовать Comparable и Comparator.


Надеемся, что наша статья была Вам полезна.  Можно записаться к нам на курсы по Java на сайте.

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr
Самоучители--узнать детальнее--