Menu
Coddy logo textTech

Интерфейс Comparator

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 45 из 87.

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

Comparator — это внешний объект, который сравнивает два объекта одного и того же типа. Это полезно, когда вам нужно несколько вариантов сортировки или когда вы не можете изменить сам класс:

import java.util.Comparator;

class NameComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

Затем вы можете передать компаратор в методы сортировки:

List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));

Collections.sort(people, new NameComparator());  // Сортировка по имени
Collections.sort(people, new AgeComparator());   // Сортировка по возрасту

Для написания лаконичного кода вы можете использовать лямбда-выражения, так как Comparator является функциональным интерфейсом:

Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));

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

challenge icon

Задание

Легко

Давайте создадим систему сортировки сотрудников, которая демонстрирует возможности интерфейса Comparator. Вы создадите несколько компараторов для сортировки сотрудников различными способами — по зарплате и по имени — без изменения самого класса Employee.

Вы организуете свой код в четырех файлах:

  • Employee.java: Создайте класс, представляющий сотрудника с тремя приватными полями: name (String), department (String) и salary (double). Включите конструктор для инициализации всех полей и методы-геттеры для каждого из них. Переопределите toString(), чтобы он возвращал: [name] ([department]) - $[salary]
  • SalaryComparator.java: Создайте компаратор, который сортирует сотрудников по зарплате в порядке убывания (сначала самые высокооплачиваемые). Реализуйте интерфейс Comparator<Employee> и его метод compare(). Используйте Double.compare() для безопасного сравнения значений зарплаты.
  • NameComparator.java: Создайте еще один компаратор, который сортирует сотрудников по имени в алфавитном порядке возрастания (от A до Z). Реализуйте Comparator<Employee> и используйте метод compareTo() класса String для сравнения.
  • Main.java: Объедините все вместе, создав список сотрудников и отсортировав их с помощью ваших компараторов. Вы получите входные данные для трех сотрудников, каждый на отдельной строке в формате: name,department,salary

    Создайте ArrayList сотрудников, затем продемонстрируйте оба подхода к сортировке:

    1. Сначала отсортируйте по зарплате, используя ваш SalaryComparator, и выведите каждого сотрудника
    2. Выведите пустую строку
    3. Затем отсортируйте по имени, используя ваш NameComparator, и выведите каждого сотрудника

Вы получите три строки входных данных, каждая из которых содержит данные о сотруднике в формате: name,department,salary

Например, строка ввода может выглядеть так: Alice,Engineering,75000.0

Не забудьте импортировать java.util.Comparator в файлах компараторов, а также java.util.ArrayList, java.util.Collections и java.util.Scanner в файле Main. Обратите внимание, как компараторы позволяют определять несколько стратегий сортировки извне — классу Employee не нужно ничего знать о том, как он может быть отсортирован!

Шпаргалка

Интерфейс Comparator позволяет создавать внешнюю логику сравнения для сортировки объектов без изменения исходного класса. Это полезно, когда вам нужно несколько вариантов сортировки.

Comparator сравнивает два объекта одного типа путем реализации метода compare():

import java.util.Comparator;

class NameComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}

Передайте компаратор в методы сортировки:

Collections.sort(people, new NameComparator());

Вы можете использовать лямбда-выражения для более краткого кода, так как Comparator является функциональным интерфейсом:

Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));

Для сравнения числовых значений используйте методы классов-оберток, такие как Double.compare(), для безопасного сравнения:

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

Ключевое отличие: Comparable определяет один естественный порядок внутри самого класса, в то время как Comparator — это отдельный класс, который может определять неограниченное количество пользовательских порядков извне.

Попробуйте сами

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Прочитать данные о трех сотрудниках из ввода
        // Формат каждой строки: имя,отдел,зарплата
        String line1 = scanner.nextLine();
        String line2 = scanner.nextLine();
        String line3 = scanner.nextLine();
        
        // TODO: Разобрать каждую строку и создать объекты Employee
        // Подсказка: используйте split(",") для разделения значений
        
        // TODO: Создать ArrayList сотрудников и добавить всех троих
        
        // TODO: Отсортировать по зарплате, используя SalaryComparator, и вывести каждого сотрудника
        // Подсказка: используйте Collections.sort(list, comparator)
        
        // TODO: Вывести пустую строку
        
        // TODO: Отсортировать по имени, используя NameComparator, и вывести каждого сотрудника
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование