Компаратор задаёт правило сравнения элементов между собой. Делает он это с помощью метода
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. Используются для полей примитивного типа, чтобы избежать лишнего боксинга. Если в классе OrderLong 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() ✨