Метод compareTo
Для упорядочивания объектов одного типа, хранящихся в массиве или коллекции, разработчики Java придумали интерфейс Comparable . В нём объявлен всего один метод, compareTo :
public interface Comparable
Интерфейс Comparable параметризирован типом объекта, который он принимает в качестве параметра в метод compareTo . В данном случае мы предупреждаем компилятор, какие типы объектов собираемся сравнивать. Если условие идентичности типов не будет выполняться, то мы получим ошибку ClassCastException . Метод compareTo в Java сравнивает вызывающий объект с объектом, переданным в качестве параметра, и возвращает в результате выполнения сравнения целое число:
- положительное, если вызывающий объект больше объекта, переданного в качестве параметра;
- отрицательное, если вызывающий объект меньше объекта, переданного в качестве параметра;
- нуль, если объекты равны.
Написание логики сравнения объектов – забота исключительно разработчика класса и определяется она желаемыми результатами при упорядочивании.
Зачем нужен метод compareTo в Java?
Программисту на Java очень часто приходиться иметь дело с массивами и списками объектов. При работе с большим количеством данных их зачастую удобно хранить в упорядоченном или отсортированном виде. Во-первых, это ускоряет работу с коллекцией при поиске нужной информации, во-вторых — упорядоченные данные визуально лучше воспринимаются.
Одним из самых простых и эффективных способов отсортировать массив объектов является метод sort() класса Arrays , а коллекцию объектов в виде списка – аналогичный метод класса Collections . Для сортировки с помощью этих методов разработчики Java предоставили нам свободу в выборе способа задания критериев сортировки: с реализацией интерфейса Comparable в классе объектов, которые мы хотим упорядочить, или с использованием интерфейса Comparator . В первом случае методы сортировки принимают набор объектов в виде массива или списка:
sort(T[]array)//сортировка массива sort(List list)// сортировка списка
sort(T[]array, Comparator comparator)//сортировка массива sort(List list, Comparator comparator)// сортировка списка
Интерфейс Comparable используется, когда мы хотим задать естественный (наиболее логичный с нашей точки зрения) порядок расположения объектов при сортировке. Он также является способом «зашить» алгоритм сравнения объектов этого класса на стадии его проектирования. Например, с помощью реализации этого интерфейса, определены критерии естественного упорядочивания в классах-обертках основных примитивных типов: Byte , Character , Long , Integer , Short , Double , Float , Boolean , String . Это также означает, что в этих классах есть реализованный метод compareTo , который при необходимости мы можем использовать в программе. Давайте посмотрим на примере сравнения строк, как реализован этот метод в классе String .
String str1="Аарон"; String str2="АAPOH"; String str3="аарон"; String str4="ААрон"; String str5="аАрон"; String str6="Берта"; String str7="берта"; String[] allStr=new String[]; Arrays.sort(allStr); for (String s:allStr) < System.out.println(s); >>
АAPOH ААрон Аарон Берта аАрон аарон берта
Как видно из примера в классе String , метод compareTo упорядочивает строки в алфавитном порядке, лексикографически и с учетом регистра. Именно такой порядок сравнения строк определен разработчиками класса String как естественный. Для более простого понимания, что такое лексикографический порядок, достаточно вспомнить, как расположены слова в языковых словарях. При сравнении чисел объекты упорядочиваются в порядке возрастания. Такая логика сравнения заложена в классах Byte , Character , Long , Integer , Shor , Double , Float .
Реализуем сравнение в своем классе
Посмотрим на примере как можно встроить возможность сравнения объектов в свой класс. При реализации метода compareto Java мы можем задать один или несколько критериев упорядочивания объектов, а также задействовать методы compareto из классов String и Integer . Например, для объектов класса User мы задаем сортировку по имени, а в случае равенства имен – по возрасту. Объекты будут располагаться в естественном порядке (по мере увеличения значения). Класс User :
public class User implements Comparable /добавляем возможность сравнивать объекты User private String name; private Integer age; private String email; public User(String name, int age, String email) < this.name = name; this.age = age; this.email = email; > @Override //реализуем метод compareTo интерфейса Comparable public int compareTo(User o) < //используем метод compareTo из класса String для сравнения имен int result = this.name.compareTo(o.name); //если имена одинаковые - сравниваем возраст, используя метод compareTo из класса Integer if (result == 0) < result = this.age.compareTo(o.age); >return result; > @Override public String toString() < return "'; >
Протестируем работу метода compareTo , реализованного в классе User , c помощью метода sort класса Collections :
public static void main(String[] args) < User user = new User("Андрей", 19, "andryha@mail.ru"); User user2 = new User("Олег", 25, "oleg@mail.ru"); User user3 = new User("Андрей", 24,"opr@google.com"); User user4 = new User("Игорь", 16, "igor@mail.ru"); User user5 = new User("Андрей", 44,"stary@google.com"); Listlist = new ArrayList<>(); list.add(user); list.add(user2); list.add(user3); list.add(user4); list.add(user5); System.out.println("-------до сортировки--------"); for (User u : list) < System.out.println(u); >System.out.println("-------после сортировки-----"); Collections.sort(list); for (User u : list) < System.out.println(u); >> > >
——-до сортировки——— ——-после сортировки——
Итак, подведем итог. Если вы — сторонник порядка во всем и хотите без лишнего кода расположить ваши объекты в массиве или списке – используете интерфейс Comparable . Реализация его метода compareTo позволяет достаточно легко встроить механизм естественного упорядочивания объектов вашего класса. Если вам приходится работать с коллекциями и массивами объектов стандартных классов, описанных в библиотеке Java, используйте уже готовые реализации compareTo в этих классах.