Найти тему
Oleg Nakrainikoff

Comparator и Comparable в Java

Оглавление

Всем привет!

Сегодня предлагаю рассмотреть данную тему, так как она нередко "всплывает" как на практике, так и на технических интервью.

Немного из теории

1. Чтобы объекты нашего класса E можно было сравнить и сортировать, он должен имплементить интерфейс Comparable, который содержит метод int compareTo(E other), для сравнения текущего объекта с объектом, переданным в качестве параметра.

2. Если в классе E, который мы хотим использовать не реализован интерфейс Comparable, или реализовал, но нас не устраивает его функциональность, то можем создать класс, реализующий Comparator<E>, определить метод compare(E o1, E o2), позволяющий сравнивать между собой 2 объекта.

3. Методы compareTo и compare возвращают: - 0, если значения равны; - отрицательное значение (обычно -1), если первый объект меньше второго; - положительное значение (обычно +1), если первый объект больше второго.

К примерам

Пример 1. Реализация Comparator<Integer> Нередко в интернете (да и что греха таить в пулл реквестах на проектах) натыкаюсь на такой пример реализации:

-2

На первый взгляд "не ну а чего такого-то?", но потом этим компоратором пытаемся отсортировать список, например: [2, 2147483647, 35, null, -2147483648, 16] и получаем:

  • переполнение типа
  • NullPointerException

Про NPE стоит однако отметить отдельно. В некоторых случаях известно и даже гарантировано, что значения не могут быть null, и проблем не возникнет. Но часто null значения допустимы по условиям задачи, и нужно предусматривать их обработку. Чаще всего null значения при сортировке выводят либо в начало списка либо в конец. Также иногда null значения можно смапить в число (например в 0), если это допустимо условиями задачи.

Перепишем компоратор, учитывая обработку null (пусть они всегда будут в конце списка) и заменив вычитание на сравнение:

-3
-4

Проверяем:

-5

Пример 2. Сортировка по двум полям. Данный пример предлагаю реализовать через Comparable. Для нашего примера возьмем класс:

-6

Имплементим Comparable<Player> и реализуем метод compareTo так, чтобы сравнение было сначала по полю name (ascending), затем по полю age (descending):

-7

Выполним сортировку:

-8

Результат:

-9

Исходный код примеров:

https://gist.github.com/onakrainikoff/5f822a8fca4b4edf39db0d3390d4751c https://gist.github.com/onakrainikoff/b95157d1d76bd75c325ffe9dd74effd7

Также подписывайтесь на

мой telegram: https://t.me/onakrainikoff

мой github https://github.com/onakrainikoff

#java #comparator #comparable