Зачем нужен компаринг в Java
Что проверяют
Понимаете ли вы, как Java упорядочивает объекты и где это используется неявно. Следом почти всегда спрашивают разницу между Comparable и Comparator и что будет с TreeSet, если compareTo не согласован с equals.
Как отвечать
Сравнение задаёт порядок, а не равенство: результат отрицательный, ноль или положительный. На нём работают List.sort, Collections.sort, Arrays.sort для объектов, stream().sorted(), TreeMap, TreeSet, PriorityQueue, Collections.max.
Comparable<T>: интерфейс изjava.lang, класс сам реализуетcompareToи получает естественный порядок. Так устроеныString,Integer,LocalDate;Comparator<T>: функциональный интерфейс изjava.util, внешний порядок без правки класса. Порядков может быть сколько угодно.
Компараторы сейчас собирают так: Comparator.comparing(Person::getLastName).thenComparingInt(Person::getAge), дальше reversed() и nullsFirst(...). Это короче и надёжнее ручной реализации.
Контракт: знак меняется при перестановке аргументов, соблюдается транзитивность, равные при сравнении элементы одинаково сравниваются с любым третьим. Согласованность с equals настоятельно рекомендуется, но не обязательна, и это важно для сортированных коллекций: TreeSet считает дубликатами элементы с compareTo == 0, а HashSet смотрит на equals. Пример: new BigDecimal("1.0") и new BigDecimal("1.00") в HashSet дают два элемента, в TreeSet один.
Где спотыкаются
Сравнивают вычитанием: return a.age - b.age. На больших значениях разность переполняет int и меняет знак. Нужен Integer.compare(a.age, b.age) или Comparator.comparingInt.
Называют Comparator классом. Это интерфейс, и после Java 8 у него много статических и default-методов, ради которых его и стоит знать.
Ломают контракт, например возвращают несимметричный результат. Сортировка может упасть с IllegalArgumentException: Comparison method violates its general contract! на одних данных и молча работать на других.