TGViewer
Уютное сообщество джавистов Уютное сообщество джавистов @javaarchivebooks · 1.87K subscribers
Post #233 2.07K
Как написать компаратор

Компаратор задаёт правило сравнения элементов между собой. Делает он это с помощью метода compare:

public int compare(T o1, T o2) {…}

Если метод вернул
▫️ число больше нуля — первый элемент больше второго
▫️ 0 — элементы равны
▫️ число меньше нуля — первый меньше второго

Простейшая и популярная реализация — вычесть одно значение из другого:

(o1, o2) -> (int) (o1.getSum() - o2.getSum())

❓ Что с этим не так?

Я всегда сомневаюсь, что из чего вычитать. Если вы отвечали на опрос дольше одной секунды, значит мы в одном лагере:) Компаратор — совсем не то место, где мозг должен спотыкаться.

В Java 8 в интерфейсе Comparator появился удобный метод:
orders.sort(comparing(Order::getSum))

Что классно:
✅ Не надо вспоминать, что из чего вычитать
✅ Легко сделать сравнение в обратном порядке:
comparing(Order::getSum).reversed()
✅ Можно учесть null:
nullsFirst(comparing(Order::getSum))
nullLast(…)
✅ Удобно сортировать по нескольким полям:
comparing(Order::getSum).thenComparing(Order::getId)

Самостоятельно обрабатывать null и писать сложные сортировки очень утомительно. Помню, как с удовольствием удаляла из проекта компараторы на 20 строк после перехода на Java 8😊

Важные нюансы:

1️⃣ comparing*

В интерфейсе Comparator также доступны методы comparingInt, comparingLong и comparingDouble. Используются для полей примитивного типа, чтобы избежать лишнего боксинга. Если в классе Order

Long id → используем comparing(Order::getId)
long id
→ comparingLong(Order::getId)

Не указывайте тип лишний раз. Для работы с объектами подойдёт обычный comparing

2️⃣ Нетривиальная работа с null*

В обычных методах легко понять, что происходит:
comparing(A).reversed().thenComparing(Б)
=
отсортировать по полю А в обратном порядке, дубликаты отсортировать по Б

Методы null* выбиваются из этой схемы.

nullsFirst(comparing(Order::getSum))

означает, что первыми будут null объекты, а существующие заказы отсортируются по сумме. Этот компаратор работает для такого кода:

orders.add(null); // эти элементы будут впереди
orders.add(new Order(…)); // эти отсортируются по полю sum

Если в списке нет null объектов, но в поле sum возможен null, придётся писать так:

…comparing(Order::getSum, nullsFirst(naturalOrder()));

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

Ответ на вопрос перед постом:
(o1, o2) -> (int) (o2.getSum() - o1.getSum())

Но лучше использовать comparing(Order::getSum).reversed() ✨
  • 👍 3
  • 😁 1
More from @javaarchivebooks
  1. Aug 17, 2026Уютное сообщество джавистов pinned «Java Работа - канал с вакансиями по Java. Если вы хоти…
  2. Aug 17, 2026Java Работа - канал с вакансиями по Java. Если вы хотите найти работу, то подписывайтесь н…
  3. Feb 26, 2026Java: быстрый старт Автор: Джейми Чан Год издания: 2021 #java #ru Скачать книгу
  4. Feb 19, 2026Java. Состояние языка и его перспективы Автор: Федор Урванов Год издания: 2023 #java #ru С…
  5. Sep 16, 2025Java: устранение проблем Автор: Лауренциу Спилкэ Год издания: 2023 #java #ru Скачать книгу
  6. Aug 30, 2025Mastering Secure Java Applications Авторы: Debopam Poddar, Joyanta Banerjee, Tarun Kumar C…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →