Интерфейс Comparator
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 45 из 87.
Хотя Comparable определяет естественный порядок класса, иногда требуется сортировать объекты разными способами. Интерфейс Comparator позволяет создать отдельную логику сравнения, не изменяя исходный class.
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 — это отдельный класс, который может определять неограниченное количество пользовательских порядков.
Задание
ЛегкоДавайте создадим систему сортировки сотрудников, демонстрирующую возможности интерфейса Comparator. Вы создадите несколько comparator'ов для сортировки сотрудников разными способами: по зарплате и по имени, не изменяя сам class Employee.
Вы организуете код в четырёх файлах:
Employee.java: Create class, представляющий сотрудника, с тремя приватными полями:name(String),department(String) иsalary(double). Добавьте constructor для инициализации всех полей и методы getter для каждого из них. ПереопределитеtoString(), чтобы он возвращал:[name] ([department]) - $[salary]SalaryComparator.java: Create comparator, который сортирует сотрудников по зарплате в descending order (сначала самые высокооплачиваемые). Implement интерфейсComparator<Employee>и его методcompare(). ИспользуйтеDouble.compare()для безопасного сравнения значений зарплаты.NameComparator.java: Create ещё один comparator, который сортирует сотрудников по имени в алфавитном порядке — ascending order (от A до Z). ImplementComparator<Employee>и используйте методcompareTo()класса String для сравнения.Main.java: Объедините всё, создав list сотрудников и отсортировав их с помощью ваших comparator'ов. Вы получите input для трёх сотрудников, каждый в отдельной строке, в формате:name,department,salaryCreate
ArrayListсотрудников, затем продемонстрируйте оба подхода к сортировке:- Сначала отсортируйте по зарплате с помощью
SalaryComparatorи выведите каждого сотрудника - Выведите пустую строку
- Затем отсортируйте по имени с помощью
NameComparatorи выведите каждого сотрудника
- Сначала отсортируйте по зарплате с помощью
Вы получите три строки input, каждая из которых содержит данные сотрудника в формате: name,department,salary
Например, строка input может выглядеть так: Alice,Engineering,75000.0
Не забудьте импортировать java.util.Comparator в файлах comparator'ов, а также java.util.ArrayList, java.util.Collections и java.util.Scanner в файле Main. Обратите внимание, как comparator'ы позволяют внешним образом определять несколько стратегий сортировки: class Employee не нужно знать ничего о том, как его можно сортировать!
Попробуйте сами
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);
// Считать трёх сотрудников из ввода
// Формат каждой строки: name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: Разобрать каждую строку и создать объекты Employee
// Hint: Используйте split(",") для разделения значений
// TODO: Создать ArrayList сотрудников и добавить всех трёх
// TODO: Отсортировать по зарплате с помощью SalaryComparator и вывести каждого сотрудника
// Hint: Используйте Collections.sort(list, comparator)
// TODO: Вывести пустую строку
// TODO: Отсортировать по имени с помощью NameComparator и вывести каждого сотрудника
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»Потренируйтесь самостоятельно: Онлайн-компилятор Java