Java udostępnia dwa interfejsy do sortowania obiektów przy użyciu elementów danych klasy:
- Porównywalny
- Komparator
Korzystanie z porównywalnego interfejsu
Obiekt porównywalny jest w stanie porównywać się z innym obiektem. Sama klasa musi implementować java.lang.Porównywalne interfejs do porównywania jego instancji.
Rozważmy klasę Film, która składa się z członków takich jak ocena, imię i nazwisko, rok. Załóżmy, że chcemy posortować listę filmów według roku premiery. Możemy zaimplementować interfejs Comparable z klasą Movie i zastąpić metodę CompareTo() interfejsu Comparable.
tablice programowania Java
Jawa
// A Java program to demonstrate use of Comparable> import> java.io.*;> import> java.util.*;> // A class 'Movie' that implements Comparable> class> Movie>implements> Comparable> {> >private> double> rating;> >private> String name;> >private> int> year;> >// Used to sort movies by year> >public> int> compareTo(Movie m)> >{> >return> this>.year - m.year;> >}> >// Constructor> >public> Movie(String nm,>double> rt,>int> yr)> >{> >this>.name = nm;> >this>.rating = rt;> >this>.year = yr;> >}> >// Getter methods for accessing private data> >public> double> getRating() {>return> rating; }> >public> String getName() {>return> name; }> >public> int> getYear() {>return> year; }> }> // Driver class> class> Main> {> >public> static> void> main(String[] args)> >{> >ArrayList list =>new> ArrayList();> >list.add(>new> Movie(>'Force Awakens'>,>8.3>,>2015>));> >list.add(>new> Movie(>'Star Wars'>,>8.7>,>1977>));> >list.add(>new> Movie(>'Empire Strikes Back'>,>8.8>,>1980>));> >list.add(>new> Movie(>'Return of the Jedi'>,>8.4>,>1983>));> >Collections.sort(list);> >System.out.println(>'Movies after sorting : '>);> >for> (Movie movie: list)> >{> >System.out.println(movie.getName() +>' '> +> >movie.getRating() +>' '> +> >movie.getYear());> >}> >}> }> |
>
bash, jeśli warunek
>Wyjście
Movies after sorting : Star Wars 8.7 1977 Empire Strikes Back 8.8 1980 Return of the Jedi 8.4 1983 Force Awakens 8.3 2015>
Załóżmy teraz, że chcemy posortować filmy również według ich ocen i nazw. Kiedy sprawimy, że element kolekcji będzie porównywalny (poprzez zaimplementowanie Comparable), mamy tylko jedną szansę na zaimplementowanie metody CompareTo(). Rozwiązanie wykorzystuje Komparator.
Korzystanie z komparatora
W przeciwieństwie do Comparable, Comparator jest zewnętrzny w stosunku do typu elementu, który porównujemy. To osobna klasa. Tworzymy wiele oddzielnych klas (które implementują Comparator) do porównywania przez różnych członków.
Klasa Collections ma drugą metodę sort() i wykorzystuje Comparator. Metoda sort() wywołuje funkcję Compare() w celu sortowania obiektów.
Aby porównać filmy według ocen, musimy zrobić 3 rzeczy:
- Utwórz klasę implementującą Comparator (a tym samym metodę Compare() wykonującą pracę wykonaną wcześniej przez funkcję CompareTo()).
- Utwórz instancję klasy Comparator.
- Wywołaj przeciążoną metodę sort(), podając jej zarówno listę, jak i instancję klasy implementującej Comparator.
Jawa
// A Java program to demonstrate Comparator interface> import> java.io.*;> import> java.util.*;> // A class 'Movie' that implements Comparable> class> Movie>implements> Comparable {> >private> double> rating;> >private> String name;> >private> int> year;> >// Used to sort movies by year> >public> int> compareTo(Movie m)> >{> >return> this>.year - m.year;> >}> >// Constructor> >public> Movie(String nm,>double> rt,>int> yr)> >{> >this>.name = nm;> >this>.rating = rt;> >this>.year = yr;> >}> >// Getter methods for accessing private data> >public> double> getRating() {>return> rating; }> >public> String getName() {>return> name; }> >public> int> getYear() {>return> year; }> }> // Class to compare Movies by ratings> class> RatingCompare>implements> Comparator {> >public> int> compare(Movie m1, Movie m2)> >{> >if> (m1.getRating() return -1; if (m1.getRating()>m2.getRating()) zwróć 1; w przeciwnym razie zwróć 0; } } // Klasa do porównywania filmów według nazwy class NameCompare implements Comparator { public int Compare(Film m1, Film m2) { return m1.getName().compareTo(m2.getName()); } } // Klasa sterownika Main { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(nowy film('Przebudzenie Mocy', 8.3, 2015)); list.add(nowy film('Gwiezdne Wojny', 8.7, 1977)); list.add(nowy film('Imperium Kontratakuje', 8.8, 1980)); list.add(nowy film('Powrót Jedi', 8.4, 1983)); // Sortuj według ocen : (1) Utwórz obiekt // ratingCompare // (2) Wywołaj Collections.sort // (3) Drukuj posortowaną listę System.out.println('Sortowane według ocen'); OcenaPorównaj ocenaPorównaj = nowa OcenaPorównaj(); Kolekcje.sort(lista, ocenaPorównaj); for (film filmowy: lista) System.out.println(film.getRating() + ' ' + film.getName() + ' ' + film.getYear()); // Wywołaj przeciążoną metodę sortowania za pomocą RatingCompare // (Te same trzy kroki jak powyżej) System.out.println('
Sortowane według nazwy'); NazwaPorównaj nazwaPorównaj = nowa nazwaPorównaj(); Kolekcje.sort(lista, nazwaPorównaj); for (film filmowy: lista) System.out.println(film.getName() + ' ' + film.getRating() + ' ' + film.getYear()); // Używa Porównywalnego do sortowania według roku System.out.println('
Sortowane według roku'); Kolekcje.sort(lista); for (film filmowy: lista) System.out.println(movie.getYear() + ' ' + movie.getRating() + ' ' + movie.getName() + ' '); } }> |
>
>
Wyjście:
Sorted by rating 8.3 Force Awakens 2015 8.4 Return of the Jedi 1983 8.7 Star Wars 1977 8.8 Empire Strikes Back 1980 Sorted by name Empire Strikes Back 8.8 1980 Force Awakens 8.3 2015 Return of the Jedi 8.4 1983 Star Wars 8.7 1977 Sorted by year 1977 8.7 Star Wars 1980 8.8 Empire Strikes Back 1983 8.4 Return of the Jedi 2015 8.3 Force Awakens>
- Porównywalne odnosi się do obiektów posiadających naturalny porządek, co oznacza, że sam obiekt musi wiedzieć, jak ma być uporządkowany. Na przykład numery rejestracyjne uczniów. Natomiast sortowanie interfejsu komparatora odbywa się poprzez osobną klasę.
- Logicznie rzecz biorąc, interfejs Comparable porównuje to odniesienie z określonym obiektem, a Comparator w Javie porównuje dwa różne dostarczone obiekty klas.
- Jeśli jakakolwiek klasa implementuje interfejs Comparable w Javie, wówczas kolekcja tego obiektu List lub Array może zostać posortowana automatycznie przy użyciu metody Collections.sort() lub Arrays.sort(), a obiekty zostaną posortowane w oparciu o naturalny porządek zdefiniowany przez metodę CompareTo.
- Podstawową cechą różnicującą jest to, że posługując się porównywalnymi, możemy posłużyć się tylko jednym porównaniem. Natomiast możemy napisać więcej niż jeden niestandardowy komparator, jak chcesz dla danego typu, a każdy z nich używa różnych interpretacji znaczenia sortowania. Podobnie jak w porównywalnym przykładzie, mogliśmy sortować tylko według jednego atrybutu, tj. roku, ale w komparatorze mogliśmy używać różnych atrybutów, takich jak ocena, nazwa i rok.
Podsumowując, jeśli sortowanie obiektów musi opierać się na porządku naturalnym, użyj opcji Comparable, natomiast jeśli sortowanie ma odbywać się na podstawie atrybutów różnych obiektów, użyj komparatora w Javie.
Java na przerwę