JavaRush /Java блог /Random UA /Метод compareTo
Автор
Владимир Портянко
Java-разработчик в Playtika

Метод compareTo

Стаття з групи Random UA
Для впорядкування об'єктів одного типу, що зберігаються в масиві або колекції, розробники Java вигадали інтерфейс Comparable. У ньому оголошено лише один метод, compareTo:
public interface Comparable<T> {
    public int compareTo(T o);
}
Метод compareTo - 1Інтерфейс Comparableпараметризований типом об'єкта, який він приймає як параметр методу compareTo. У разі ми попереджаємо компілятор, які типи об'єктів збираємося порівнювати. Якщо умова ідентичності типів нічого очікувати виконуватися, ми отримаємо помилку ClassCastException. Метод compareToJava порівнює викликаючий об'єкт з об'єктом, переданим як параметр, і повертає в результаті виконання порівняння ціле число:
  • позитивне, якщо об'єкт, що викликає, більше об'єкта, переданого в якості параметра;
  • негативне, якщо об'єкт, що викликає, менший за об'єкт, переданий як параметр;
  • нуль, якщо об'єкти дорівнюють.
Написання логіки порівняння об'єктів – турбота виключно розробника класу та визначається вона бажаними результатами при упорядкуванні.

Навіщо потрібен метод compareTo в Java?

Програмістові на Java дуже часто доводиться мати справу з масивами та списками об'єктів. Працюючи з великою кількістю даних їх найчастіше зручно зберігати у впорядкованому чи відсортованому вигляді. По-перше, це прискорює роботу з колекцією під час пошуку потрібної інформації, по-друге — упорядковані дані візуально краще сприймаються.
Метод compareTo - 2
Одним із найпростіших і найефективніших способів відсортувати масив об'єктів є метод 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.

Реалізуємо порівняння у своєму класі

Подивимося з прикладу як можна вбудувати можливість порівняння об'єктів у свій клас. При реалізації методу comparetoJava ми можемо задати один або кілька критеріїв упорядкування об'єктів, а також використовувати методи 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в цих класах.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ