Для впорядкування об'єктів одного типу, що зберігаються в масиві або колекції, розробники Java вигадали інтерфейс
Одним із найпростіших і найефективніших способів відсортувати масив об'єктів є метод
Comparable
. У ньому оголошено лише один метод, compareTo
:
public interface Comparable<T> {
public int compareTo(T o);
}
Інтерфейс Comparable
параметризований типом об'єкта, який він приймає як параметр методу compareTo
. У разі ми попереджаємо компілятор, які типи об'єктів збираємося порівнювати. Якщо умова ідентичності типів нічого очікувати виконуватися, ми отримаємо помилку ClassCastException
. Метод compareTo
Java порівнює викликаючий об'єкт з об'єктом, переданим як параметр, і повертає в результаті виконання порівняння ціле число:
- позитивне, якщо об'єкт, що викликає, більше об'єкта, переданого в якості параметра;
- негативне, якщо об'єкт, що викликає, менший за об'єкт, переданий як параметр;
- нуль, якщо об'єкти дорівнюють.
Навіщо потрібен метод compareTo в Java?
Програмістові на Java дуже часто доводиться мати справу з масивами та списками об'єктів. Працюючи з великою кількістю даних їх найчастіше зручно зберігати у впорядкованому чи відсортованому вигляді. По-перше, це прискорює роботу з колекцією під час пошуку потрібної інформації, по-друге — упорядковані дані візуально краще сприймаються.sort()
класу Arrays
, а колекцію об'єктів у вигляді списку – аналогічний метод класу Collections
. Для сортування за допомогою цих методів розробники Java надали нам свободу у виборі способу завдання критеріїв сортування: з реалізацією інтерфейсу Comparable
в класі об'єктів, які ми хочемо впорядкувати, або з використанням інтерфейсу Comparator
. У першому випадку методи сортування приймають набір об'єктів у вигляді масиву чи списку:
sort(T[]array)//сортування массива
sort(List<T> list)// сортування списка
а в другому - плюс ще реалізацію інтерфейсу Comparator
:
sort(T[]array, Comparator <? super T> comparator)//сортування массива
sort(List<T> list, Comparator <? super T> 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[]{str1,str2,str3,str4, str5,str6, str7};
Arrays.sort(allStr);
for (String s:allStr){
System.out.println(s);
}
}
Якщо цей код виконати в методі main
, то отримаємо такий результат:
АAPOH
ААрон
Аарон
Берта
аАрон
аарон
берта
Як видно з прикладу в класі String
, метод compareTo
упорядковує рядки в алфавітному порядку, лексикографічно та з урахуванням регістру. Саме такий порядок порівняння рядків визначено розробниками класу String
як природний. Для простішого розуміння, що таке лексикографічний порядок, досить згадати, як розташовані слова в мовних словниках. При порівнянні чисел об'єкти впорядковуються у порядку зростання. Така логіка порівняння закладена в класах Byte
, Character
, Long
, Integer
, Shor
, Double
, Float
.
Реалізуємо порівняння у своєму класі
Подивимося з прикладу як можна вбудувати можливість порівняння об'єктів у свій клас. При реалізації методуcompareto
Java ми можемо задати один або кілька критеріїв упорядкування об'єктів, а також використовувати методи compareto
з класів String
і Integer
. Наприклад, для об'єктів класу User
ми задаємо сортування на ім'я, а у разі рівності імен – за віком. Об'єкти будуть розміщені в природному порядку (у міру збільшення значення). Клас User
:
public class User implements Comparable <User>{//добавляем возможность сравнивать об'єкты 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 "{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
Протестуємо роботу методу compareTo
, реалізованого в класі User
, за допомогою методу 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");
List<User> list = 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);
}
}
}
}
Результат роботи методу main
:
-------до сортировки--------
{name='Андрей', age=19, email='andryha@mail.ru'}
{name='Олег', age=25, email='oleg@mail.ru'}
{name='Андрей', age=24, email='opr@google.com'}
{name='Игорь', age=16, email='igor@mail.ru'}
{name='Андрей', age=44, email='stary@google.com'}
-------после сортировки-----
{name='Андрей', age=19, email='andryha@mail.ru'}
{name='Андрей', age=24, email='opr@google.com'}
{name='Андрей', age=44, email='stary@google.com'}
{name='Игорь', age=16, email='igor@mail.ru'}
{name='Олег', age=25, email='oleg@mail.ru'}
Отже, підіб'ємо підсумок. Якщо ви прихильник порядку у всьому і хочете без зайвого коду розташувати ваші об'єкти в масиві або списку - використовуєте інтерфейс Comparable
. Реалізація його методу compareTo дозволяє легко вбудувати механізм природного впорядкування об'єктів вашого класу. Якщо вам доводиться працювати з колекціями та масивами об'єктів стандартних класів, які описані в бібліотеці Java, використовуйте вже готові реалізації compareTo
в цих класах.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ