Aby uporządkować obiekty tego samego typu przechowywane w tablicy lub kolekcji, programiści Java wymyślili rozszerzenie
Jednym z najprostszych i najskuteczniejszych sposobów sortowania tablicy obiektów jest metoda
Comparable
. Deklaruje tylko jedną metodę compareTo
:
public interface Comparable<T> {
public int compareTo(T o);
}
Interfejs Comparable
jest parametryzowany przez typ obiektu, który przyjmuje jako parametr metody compareTo
. W takim przypadku ostrzegamy kompilator, jakie typy obiektów będziemy porównywać. Jeśli warunek tożsamości typu nie zostanie spełniony, otrzymamy błąd ClassCastException
. Metoda compareTo
w Javie porównuje obiekt wywołujący z obiektem przekazanym jako parametr i w wyniku porównania zwraca liczbę całkowitą:
- dodatnie, jeśli obiekt wywołujący jest większy niż obiekt przekazany jako parametr;
- wartość ujemna, jeśli obiekt wywołujący jest mniejszy niż obiekt przekazany jako parametr;
- null, jeśli obiekty są równe.
Dlaczego metoda CompareTo jest potrzebna w Javie?
Programista Java bardzo często ma do czynienia z tablicami i listami obiektów. Podczas pracy z dużą ilością danych często wygodnie jest przechowywać je w zorganizowanej lub posortowanej formie. Po pierwsze, przyspiesza pracę z kolekcją w poszukiwaniu potrzebnych informacji, a po drugie, uporządkowane dane są lepiej postrzegane wizualnie.sort()
klasowa Arrays
, a zbiór obiektów w formie listy jest podobną metodą klasową Collections
. Aby sortować przy użyciu tych metod, programiści Java dali nam swobodę wyboru sposobu określenia kryteriów sortowania: implementując interfejs Comparable
w klasie obiektów, które chcemy sortować, lub używając metody Comparator
. W pierwszym przypadku metody sortujące akceptują zbiór obiektów w postaci tablicy lub listy:
sort(T[]array)//sortowanie массива
sort(List<T> list)// sortowanie списка
a w drugim - plus kolejna implementacja interfejsu Comparator
:
sort(T[]array, Comparator <? super T> comparator)//sortowanie массива
sort(List<T> list, Comparator <? super T> comparator)// sortowanie списка
Interfejs Comparable
stosujemy wtedy, gdy podczas sortowania chcemy ustawić naturalną (najbardziej logiczną z naszego punktu widzenia) kolejność obiektów. Jest to także sposób na „okablowanie” algorytmu porównywania obiektów tej klasy na etapie projektowania. Przykładowo, wykorzystując implementację tego interfejsu, definiowane są kryteria naturalnego porządku w klasach wrapperów głównych typów pierwotnych: , Byte
, Character
, Long
, Integer
, Short
, Double
, Float
, Boolean
. String
Oznacza to również, że klasy te posiadają zaimplementowaną metodę compareTo
, którą w razie potrzeby możemy wykorzystać w programie. Przyjrzyjmy się przykładowi porównania ciągów , aby zobaczyć, jak ta metoda jest zaimplementowana w klasie 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);
}
}
Jeśli wykonamy ten kod w metodzie main
, otrzymamy następujący wynik:
АAPOH
ААрон
Аарон
Берта
аАрон
аарон
берта
Jak widać w przykładzie w klasie String
, metoda compareTo
porządkuje ciągi znaków alfabetycznie, leksykograficznie i uwzględnia wielkość liter. To właśnie tę kolejność porównywania ciągów definiują twórcy klasy String
jako naturalną. Aby łatwiej zrozumieć, jaki jest porządek leksykograficzny, wystarczy przypomnieć sobie, jak ułożone są słowa w słownikach językowych. Podczas porównywania liczb obiekty są porządkowane w kolejności rosnącej. Ta logika porównania jest osadzona w klasach Byte
, Character
, Long
, Integer
, Shor
, Double
.Float
Zaimplementujmy porównanie w naszej klasie
Przyjrzyjmy się przykładowi, w jaki sposób można zbudować możliwość porównywania obiektów w swojej klasie. Implementująccompareto
metodę Java, możemy określić jedno lub więcej kryteriów porządkowania obiektów, a także skorzystać z metod compareto
z klas String
i Integer
. Przykładowo dla obiektów klas User
ustawiamy sortowanie według nazwy, a w przypadku jednakowych nazw, według wieku. Obiekty zostaną ułożone w swoim naturalnym porządku (wraz ze wzrostem wartości). Klasa User
:
public class User implements Comparable <User>{//добавляем возможность сравнивать obiektы 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 + '\'' +
'}';
}
Przetestujmy działanie metody compareTo
zaimplementowanej w klasie User
przy pomocy metody sort
klasowej Collections
:
public static void main(String[] args) {
User user = new User(„Andriej”, 19, "andryha@mail.ru");
User user2 = new User("Олег", 25, "oleg@mail.ru");
User user3 = new User(„Andriej”, 24,"opr@google.com");
User user4 = new User("Igor", 16, "igor@mail.ru");
User user5 = new User(„Andriej”, 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);
}
}
}
}
Wynik metody 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'}
Podsumujmy więc. Jeśli jesteś zwolennikiem porządku we wszystkim i chcesz uporządkować swoje obiekty w tablicę lub listę bez niepotrzebnego kodu, skorzystaj z interfejsu Comparable
. Implementacja metody CompareTo znacznie ułatwia zbudowanie mechanizmu naturalnego porządkowania obiektów w klasie. Jeśli musisz pracować z kolekcjami i tablicami obiektów klas standardowych opisanych w bibliotece Java, skorzystaj z gotowych implementacji compareTo
w tych klasach.
GO TO FULL VERSION