Java Comparable i Comparator razlike
U prethodnom učenju prioritetni red, pomenuli smo Comparable i Comparator, pa nastavimo sa perspektive intervjuera.
Onog dana, Mali Petar je išao na intervju u Ma Fengwo, a intervjuer Wang Yi ga je odmah pitao: Koji su razlike između Comparable i Comparator? Mali Petar se smejao, jer pre tri godine, 2021. godine, na Putu ka boljoj Javi je video ovo pitanje😆.
Comparable i Comparator su dva Java interfejsa, i iz samog imena možemo pročitati njihovu sličnost: poređenje dva objekta na određeni način.
Ali koje su u suštini razlike između njih? Dođite sa mnom, krećemo u napredovanje!
01,Comparable
Comparable interfejs je vrlo jednostavan, izvorni kod je prikazan ispod.
public interface Comparable<T> {
int compareTo(T t);
}Ako klasa implementira Comparable interfejs (samo treba uraditi jednu stvar, prepisati compareTo() metod), onda može porediti objekte koje je napravila prema sopstvenim pravilima. Evo jednog primera.
public class Programer implements Comparable<Programer> {
private int age;
private String name;
public Programer(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Programer o) {
return this.getAge() - o.getAge();
}
public static void main(String[] args) {
Programer petar = new Programer(19,"Marko Marković");
Programer jovan = new Programer(16,"Petar Petrović");
if (petar.compareTo(jovan) < 0) {
System.out.println(petar.getName() + "je mlađi i sposobniji");
} else {
System.out.println(jovan.getName() + "je mlađi i sposobniji");
}
}
}U gornjem primeru, napravio sam klasu Programer koja ima dva polja: age i name. Programer klasa implementira Comparable interfejs i prepisuje compareTo() metod.
Rezultat programa je "Petar Petrović je mlađi i sposobniji", jer je tri godine mlađi od Marko Marković. Da li ima dokaza za ovaj rezultat?
Dokaz je u compareTo() metodu, čija povratna vrednost može biti negativan broj, nula ili pozitivan broj, što znači da je objekat manji, jednak ili veći od objekta sa kojim se poredi prema pravilima sortiranja. Ako se ne može porediti tip navedenog objekta sa ovim objektom, baca se ClassCastException izuzetak (od kada postoje generici, ovo se retko dešava).
02,Comparator
Comparator interfejs je mnogo kompleksniji od Comparable, ali osnovne metode su samo dve, pogledajmo izvorni kod.
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}Prva metoda compare(T o1, T o2) vraća negativan broj, nulu ili pozitivan broj, što znači da je prvi objekat manji, jednak ili veći od drugog objekta.
Druga metoda equals(Object obj) zahteva Object kao parametar i proverava da li je taj Object jednak sa Comparatorom.
Ponekad želimo da klasa ostane u originalnom obliku, ne želimo da implementira Comparable interfejs, ali i dalje moramo da ih poredimo, šta da radimo?
Onda nam Comparator pomaže, pogledajmo primer.
1)Nepromenjena Programer klasa.
public class Programer {
private int age;
private String name;
public Programer(int age, String name) {
this.age = age;
this.name = name;
}
}Programer klasa ima dva polja: age i name, što znači da se ova klasa može sortirati prema age ili name.
2)Pogledajmo implementaciju Comparator interfejsa.
public class ProgramerComparator implements Comparator<Programer> {
@Override
public int compare(Programer o1, Programer o2) {
return o1.getAge() - o2.getAge();
}
}Poređenje prema age. Naravno, možete implementirati i drugi komparator za prirodno sortiranje prema name, kao u primeru ispod.
public class ProgramerNameComparator implements Comparator<Programer> {
@Override
public int compare(Programer o1, Programer o2) {
if (o1.getName().hashCode() < o2.getName().hashCode()) {
return -1;
} else if (o1.getName().hashCode() == o2.getName().hashCode()) {
return 0;
}
return 1;
}
}3)Pogledajmo test klasu.
Programer petar = new Programer(19,"Marko Marković");
Programer jovan = new Programer(16,"Petar Petrović");
Programer wangyi = new Programer(28,"Nikola Nikolić");
List<Programer> list = new ArrayList<>();
list.add(petar);
list.add(jovan);
list.add(wangyi);
list.sort(new ProgramerComparator());
for (Programer c : list) {
System.out.println(c.getName());
}Napravio sam tri objekta s različitim age i name, i dodao ih u List. Zatim sam koristio sort() metodu List za sortiranje, pogledajmo rezultat.
Petar Petrović
Marko Marković
Nikola NikolićTo znači da je Petar Petrović mlađi od Marko Marković, pa je na prvom mestu; Nikola Nikolić je stariji od Marko Marković, pa je na trećem mestu. Potpuno se slaže sa našim očekivanjima.
Pogledajmo izvorni koda sort metode:
public void sort(Comparator<? super E> c) {
// čuva trenutnu vrednost modCount reda za detekciju nelegalne sort operacije
final int expectedModCount = modCount;
// poziva Arrays.sort za sortiranje elementData niza koristeći prosleđeni komparator c
Arrays.sort((E[]) elementData, 0, size, c);
// proverava da li je modCount izmenjen tokom operacije, ako jeste baca izuzetak konkurentne modifikacije
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
// povećava modCount vrednost, označavajući da je red izmenjen
modCount++;
}Možete videti da je parametar upravo Comparator interfejs, i koristi se generik Comparator<? super E> c.
03,Koji treba koristiti?
Kroz dva gornja primera možemo uporediti razlike između Comparable i Comparator:
- Ako klasa implementira Comparable interfejs, to znači da se objekti te klase mogu direktno porediti (sortirati), ali način poređenja (sortiranja) je samo jedan, vrlo jednostavan.
- Ako klasa želi da ostane u originalnom obliku, ali treba različite načine poređenja (sortiranja), možete napraviti prilagođeni komparator (implementirati Comparator interfejs).
- Comparable interfejs je u
java.langpaketu, aComparatorinterfejs je ujava.utilpaketu, nisu direktni braća, ali mogu se zvati rodjaka.
Dajmo neproporan primer. Hoću iz Luoyanga da idem u Peking da vidim Kineski zid, da osetim osećaj heroja, ili avionom ili brzim vozom; ali ako je Sun Wukong, okrene se i stigne. Koja je razlika između mene i Sun Wukonga?
Sun Wukong je sam implementirao Comparable interfejs (u njegovo vreme nije bilo aviona i brzih vozova, nije imao izbora), a ja mogu koristiti Comparator interfejs (moderni saobraćajni sredstva).
Dobro, o Comparable i Comparator ćemo za sada ovoliko. Ukratko, ako sortiranje objekata treba da bude zasnovano na prirodnom redosledu, odaberite Comparable, ako treba sortirati prema različitim osobinama objekta, odaberite Comparator.
