В чем разница между Comparable и Comparator? Это очень популярный вопрос на собеседовании по Java для начального и среднего уровня, не так ли?

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

Но мы обычно упускаем из виду назначение или варианты использования этих интерфейсов.

Прежде чем мы поймем различия, нам нужно понять, что такое естественный порядок?

Естественный порядок

Позвольте задать вам вопрос — если я не предоставлю никакой дополнительной информации и дам вам список чисел или строковых значений, таких как имена, то как вы их отсортируете?

Вы бы сказали числа в порядке возрастания и имена в алфавитном порядке.

Но почему? Вы бы сказали, что это кажется естественным, не так ли?

Что же такое естественный порядок? Нам не нужна дополнительная информация, мы просто умеем их сортировать.

Теперь представьте, что я прошу вас отсортировать список студентов.

Вы, наверное, скажете — как? По номеру списка, по имени, по дате рождения или по отметкам?

Здесь нам нужна дополнительная информация, потому что Стьюдент не имеет естественного порядка.

Сопоставимый против компаратора

Используя Comparable https://www.youtube.com/watch?v=E0jkSl-QPEk&list=PLpxcSt9FGVVHp2QywnxaGNQGMErthxRfU&index=16

Использование компаратора https://www.youtube.com/watch?v=SJFa9sldCCk&list=PLpxcSt9FGVVHp2QywnxaGNQGMErthxRfU&index=17

Теперь мы возвращаемся к вопросу.

Все вторично, но главное, что нужно помнить об этих интерфейсах, это то, что если мы определяем естественный порядок сущности/класса, то мы используем Comparable.

Естественный порядок == Сопоставимый

Каков был бы естественный порядок Студента?

Завершение естественного порядка объекта зависит от требования и варианта использования.

В случае класса Student, если мы решим, что это будет по номеру списка, мы реализуем интерфейс Comparable и предоставим логику для сравнения их по номерам списка.

class Student implements Comparable<Student> {
        private int rollNo;
        private String name;
        private LocalDate dob;

        Student(int rollNo, String name, LocalDate dob) {
            this.rollNo = rollNo;
            this.name = name;
            this.dob = dob;

        }

        @Override
        public String toString() {
            return "Student{" +
                    "rollNo=" + rollNo +
                    ", name='" + name + '\'' +
                    ", dob=" + dob +
                    '}';
        }

        @Override
        public int compareTo(Student o) {
            return this.rollNo - o.rollNo;
        }
    }

Пользовательская сортировка

Мы выбрали номер списка, чтобы быть естественным порядком студентов. Но что, если я хочу отсортировать их по отметкам или возрасту?

Чтобы применить пользовательскую сортировку, мы используем интерфейс Comparator.

Компаратор имеет множество служебных методов, которые мы можем использовать для предоставления пользовательских критериев сортировки.

Вот пример сортировки учеников по имени.

students.sort(Comparator.comparing(Student::getName));

Или мы можем объединить несколько атрибутов.

//sort by name and date of birth
students.sort(Comparator.comparing(Student::getName).thenComparing(Student::getDob));

Заключение

Comparable используется для определения естественного порядка сущности.

Comparator - это все о пользовательской сортировке.