Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions lessons/java-core/038/Comparable and Comparator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Механизмы сравнения. Comparable и Comparator

В разработке периодически возникают ситуации, когда требуется произвести сравнение объектов. Чаще всего – для сортировки
в рамках коллекции, реже – в условных конструкциях (там обычно хватает более простых выражений).

В целом, мы знакомы с операторами сравнения `«>»` и `«<»`. Но вот незадача: они работают лишь для примитивных типов (и
то не для всех). Мы не можем использовать эти операторы для сравнения объектов целиком.

Для решения возникшей проблемы в Java существуют 2 интерфейса: `Comparable` и `Comparator`. Как переопределенный
метод `equals()` реализует `«==»` на максималках, позволяя определять равенство объектов, так и реализации `Comparable`
и `Comparator` реализуют гибкое сравнение, заменяя собой сразу 3 отношения: `«>»`, `«<»` и `«==»`.

Предлагаю ознакомиться с синтаксисом и примерами применения посредством
[статьи](https://metanit.com/java/tutorial/5.6.php) ниже. Там упоминается незнакомая нам коллекция типа `Set`, но в
рамках статьи она не на что не влияет, можно проигнорировать ее упоминания, а примеры адаптировать под использование
списка и вызов у него метода сортировки (будет даже нагляднее)

На что стоит обратить внимание:

1. Связь возвращаемого из `compareTo()`/`compare()` целочисленного значения и привычных нам `«>»`, `«<»` и `«==»`:
- `«>»` равносильно возвращению из метода «1» (в широком смысле – любого положительного числа);
- `«<»` – возврат отрицательного числа (опять же, обычно – «-1»);
- `«==»` равносильно 0 (нулю).
2. `Comparable` – интерфейс, который должен быть имплементирован классом, объекты которого мы планируем сравнивать
(например, `String` имплементирует `Comparable`). `Comparator` – интерфейс, который расширяется конечными
реализациями _Comparator’а_ – отдельными классами-компараторами. Обычно эти классы реализуют в виде анонимным
классов (или лямбда-выражений, но с ними мы еще не знакомы);
3. `Comparable` подходит для простого сравнения, когда достаточно сравнить объекты одним конкретным способом (например,
строки всегда сравниваются в алфавитном порядке. Точнее, по номерам символов, из которых строки состоят).
4. `Comparator` подходит для ситуаций, когда объект нужно сравнивать по разным критериям в зависимости от ситуации.
Например, мы хотим иметь возможность отсортировать коллекцию сущностей _Человек_ по росту. А в другой ситуации – по
весу. Для каждой из этих ситуаций нам нужен отдельный компаратор;
5. В отличии от `Comparable`, `Comparator` поддерживает сложную сортировку. Используя метод `thenComparing()`* можно
реализовать сортировку коллекции по нескольким параметрам: скажем, сначала отсортировать коллекцию сущностей
_Человек_ по росту, а уже элементы с одинаковым ростом – по весу. Или наоборот.
6. Также `Comparator` содержит методы, позволяющие указать место `null`-объектов при сортировке (в начале или в
конце) – `nullsFirst()` и `nullsLast()` – и методы, определяющие порядок сортировки для Comparable-объектов (прямой
или обратный) – `reverseOrder()` и `naturalOrder()`.

> *thenComparing() перегружен. На данном этапе нас интересует реализация с единственным параметром типа Comparator.

На первый взгляд, наличие в Java и `Comparable`, и `Comparator` может показаться избыточным. Однако их сочетание и
грамотное использование может сильно упростить жизнь. Главное понимать, что зона ответственности `Comparable` –
непосредственно сравнение объектов (одним единственным верным в рамках логики программы образом), а зоной
ответственности `Comparator` являются сортировки (или определение порядка элементов в некоторых структурах данных).
Именно поэтому реализация `Comparable` для сущности может быть только одна, а реализаций `Comparator` – неограниченное
количество, включая совместное использование различных реализаций через `thenComparing()`.

#### С теорией на сегодня все!

![img.png](../../../commonmedia/defaultFooter.jpg)

Переходим к практике:

## Задача 1:

Используя классы-сущности из
[задачи к уроку 21](https://github.com/KFalcon2022/practical-tasks/tree/master/src/com/walking/lesson21_immutable_object/model)
реализуйте сортировку машин по:

- Номеру;
- Цвету;
- Году;
- Номеру и году.

Используйте список для хранения и сортировки коллекции машин.

## Задача 2:

Используя классы-сущности из
[задачи к уроку 21](https://github.com/KFalcon2022/practical-tasks/tree/master/src/com/walking/lesson21_immutable_object/model)
имплементируйте `Comparable` для `Car` таким образом, чтобы машины сравнивались по полю `identifier`.
Объекты `CarIdentifier` предлагаю сравнивать по номеру и году (если номера почему-то совпали).

Также реализуйте сортировку коллекции машин в прямом и обратном порядке.

> Если что-то непонятно или не получается – welcome в комменты к посту или в лс:)
>
> Канал: https://t.me/ViamSupervadetVadens
>
> Мой тг: https://t.me/ironicMotherfucker
>
> **Дорогу осилит идущий!**