Comparable и Comparator
Когда объектам нужен порядок
Для чисел и строк порядок уже понятен, но для пользовательских объектов Java не может угадать,
что считать «меньше» или «больше». Один и тот же объект можно сравнивать по имени, цене, дате или любому другому признаку.
Для описания порядка используются Comparable и Comparator.
Comparable: естественный порядок класса
Если у класса есть один основной, естественный способ упорядочивания, он может реализовать
Comparable<T> и метод compareTo().
class Level implements Comparable<Level> {
private final int value;
Level(int value) {
this.value = value;
}
@Override
public int compareTo(Level other) {
return Integer.compare(value, other.value);
}
}
Результат сравнения меньше нуля означает «этот объект раньше», ноль — одинаковую позицию в порядке,
а значение больше нуля — «этот объект позже». Не нужно возвращать именно -1,
0 или 1: важен знак результата.
Comparator: отдельное правило сравнения
Когда способов сортировки несколько или класс менять нельзя, правило выносится в
Comparator<T>.
class LengthComparator implements Comparator<String> {
@Override
public int compare(String left, String right) {
return Integer.compare(left.length(), right.length());
}
}
List<String> names = new ArrayList<>(List.of("Bob", "Alexander", "Ann"));
names.sort(new LengthComparator());
Теперь строки сортируются по длине, хотя их собственный естественный порядок остаётся алфавитным. Так можно держать рядом несколько независимых правил сравнения для одного типа.
Естественный и обратный порядок
Для типов, которые уже реализуют Comparable, стандартная библиотека предоставляет готовые компараторы.
List<Integer> numbers = new ArrayList<>(List.of(3, 1, 2));
numbers.sort(Comparator.naturalOrder());
numbers.sort(Comparator.reverseOrder());
equals(),
некоторые структуры и алгоритмы могут вести себя неожиданно. Такое расхождение должно быть осознанным.