Dlaczego Comparable
używana jest Java ? Dlaczego ktoś miałby wdrażać Comparable
na zajęciach? Jaki jest przykład z życia, w którym trzeba wdrożyć porównywalne?
Dlaczego Comparable
używana jest Java ? Dlaczego ktoś miałby wdrażać Comparable
na zajęciach? Jaki jest przykład z życia, w którym trzeba wdrożyć porównywalne?
Odpowiedzi:
Oto próbka z prawdziwego życia. Zauważ, że String
również implementuje Comparable
.
class Author implements Comparable<Author>{
String firstName;
String lastName;
@Override
public int compareTo(Author other){
// compareTo should return < 0 if this is supposed to be
// less than other, > 0 if this is supposed to be greater than
// other and 0 if they are supposed to be equal
int last = this.lastName.compareTo(other.lastName);
return last == 0 ? this.firstName.compareTo(other.firstName) : last;
}
}
później..
/**
* List the authors. Sort them by name so it will look good.
*/
public List<Author> listAuthors(){
List<Author> authors = readAuthorsFromFileOrSomething();
Collections.sort(authors);
return authors;
}
/**
* List unique authors. Sort them by name so it will look good.
*/
public SortedSet<Author> listUniqueAuthors(){
List<Author> authors = readAuthorsFromFileOrSomething();
return new TreeSet<Author>(authors);
}
last
?
Porównywalne definiuje naturalne uporządkowanie. Oznacza to, że definiujesz go, gdy jeden obiekt powinien być uważany za „mniejszy niż” lub „większy niż”.
Załóżmy, że masz kilka liczb całkowitych i chcesz je posortować. To całkiem proste, po prostu umieść je w posortowanej kolekcji, prawda?
TreeSet<Integer> m = new TreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted
Ale teraz załóżmy, że mam jakiś niestandardowy obiekt, dla którego sortowanie ma dla mnie sens, ale jest niezdefiniowane. Powiedzmy, że mam dane reprezentujące dzielnice według kodu pocztowego z gęstością zaludnienia i chcę posortować je według gęstości:
public class District {
String zipcode;
Double populationDensity;
}
Teraz najłatwiejszym sposobem ich sortowania jest zdefiniowanie ich za pomocą naturalnego uporządkowania poprzez zaimplementowanie Comparable, co oznacza, że istnieje standardowy sposób definiowania tych obiektów w celu ich uporządkowania .:
public class District implements Comparable<District>{
String zipcode;
Double populationDensity;
public int compareTo(District other)
{
return populationDensity.compareTo(other.populationDensity);
}
}
Zauważ, że możesz zrobić to samo, definiując komparator. Różnica polega na tym, że komparator definiuje logikę porządkowania poza obiektem . Może w osobnym procesie muszę uporządkować te same obiekty według kodu pocztowego - w takim przypadku kolejność niekoniecznie jest własnością obiektu lub różni się od naturalnego uporządkowania obiektów. Możesz użyć zewnętrznego komparatora, aby zdefiniować niestandardową kolejność liczb całkowitych, na przykład sortując je według wartości alfabetycznej.
Zasadniczo logika porządkowania musi gdzieś istnieć. To może być -
w samym obiekcie, jeśli jest naturalnie porównywalny (rozciąga liczby całkowite Comparable -eg)
dostarczane w zewnętrznym komparatorze, jak w powyższym przykładzie.
TreeSet<Integer>
zamiast tego TreeMap<Integer>
, ponieważ to drugie nie istnieje, mapy drzew są zawsze <Key,Value>
-parami. Przy okazji, hipoteza TreeMap<District, Object>
działałaby tylko wtedy, gdyby District wdrożyło Porównywalny, prawda? Wciąż próbuję to zrozumieć
Cytowane z javadoc;
Ten interfejs narzuca całkowite uporządkowanie obiektów każdej klasy, która go implementuje. To uporządkowanie jest określane jako naturalne uporządkowanie klasy, a metoda compareTo klasy jest nazywana jej naturalną metodą porównania.
Listy (i tablice) obiektów, które implementują ten interfejs, mogą być sortowane automatycznie według Collections.sort (i Arrays.sort). Obiekty, które implementują ten interfejs, mogą być używane jako klucze w posortowanej mapie lub jako elementy w posortowanym zestawie, bez konieczności określania komparatora.
Edytuj: ... i pogrubiłem ważny bit.
Fakt, że klasa implementuje, Comparable
oznacza, że możesz pobrać dwa obiekty z tej klasy i porównać je. Niektóre klasy, takie jak pewne kolekcje (funkcja sortowania w kolekcji), które utrzymują obiekty w porządku, polegają na tym, że są porównywalne (aby posortować, musisz wiedzieć, który obiekt jest „największy” i tak dalej).
Większość powyższych przykładów pokazuje, jak ponownie użyć istniejącego porównywalnego obiektu w funkcji compareTo. Jeśli chcesz zaimplementować własne porównanie Aby porównać dwa obiekty tej samej klasy, powiedz obiekt AirlineTicket, który chcesz posortować według ceny (na pierwszym miejscu jest mniej), a następnie liczba międzylądowań (ponownie, mniej to na pierwszym miejscu), wykonasz następujące czynności:
class AirlineTicket implements Comparable<Cost>
{
public double cost;
public int stopovers;
public AirlineTicket(double cost, int stopovers)
{
this.cost = cost; this.stopovers = stopovers ;
}
public int compareTo(Cost o)
{
if(this.cost != o.cost)
return Double.compare(this.cost, o.cost); //sorting in ascending order.
if(this.stopovers != o.stopovers)
return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending
return 0;
}
}
Łatwym sposobem na zaimplementowanie wielu porównań pól jest porównanie łańcucha Guava - wtedy możesz powiedzieć
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(lastName, that.lastName)
.compare(firstName, that.firstName)
.compare(zipCode, that.zipCode)
.result();
}
zamiast
public int compareTo(Person other) {
int cmp = lastName.compareTo(other.lastName);
if (cmp != 0) {
return cmp;
}
cmp = firstName.compareTo(other.firstName);
if (cmp != 0) {
return cmp;
}
return Integer.compare(zipCode, other.zipCode);
}
}
Na przykład, gdy chcesz mieć posortowaną kolekcję lub mapę
Porównywalny służy do porównywania wystąpień Twojej klasy. Możemy porównywać instancje na wiele sposobów, dlatego musimy zaimplementować metodę compareTo
, aby wiedzieć, jak (atrybuty) chcemy porównać instancje.
Dog
klasa:package test;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Dog d1 = new Dog("brutus");
Dog d2 = new Dog("medor");
Dog d3 = new Dog("ara");
Dog[] dogs = new Dog[3];
dogs[0] = d1;
dogs[1] = d2;
dogs[2] = d3;
for (int i = 0; i < 3; i++) {
System.out.println(dogs[i].getName());
}
/**
* Output:
* brutus
* medor
* ara
*/
Arrays.sort(dogs, Dog.NameComparator);
for (int i = 0; i < 3; i++) {
System.out.println(dogs[i].getName());
}
/**
* Output:
* ara
* medor
* brutus
*/
}
}
Main
klasa:package test;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Dog d1 = new Dog("brutus");
Dog d2 = new Dog("medor");
Dog d3 = new Dog("ara");
Dog[] dogs = new Dog[3];
dogs[0] = d1;
dogs[1] = d2;
dogs[2] = d3;
for (int i = 0; i < 3; i++) {
System.out.println(dogs[i].getName());
}
/**
* Output:
* brutus
* medor
* ara
*/
Arrays.sort(dogs, Dog.NameComparator);
for (int i = 0; i < 3; i++) {
System.out.println(dogs[i].getName());
}
/**
* Output:
* ara
* medor
* brutus
*/
}
}
Oto dobry przykład, jak używać porównywalnego w Javie:
http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2
Kiedy implementujesz Comparable
interfejs, musisz zaimplementować metodę compareTo()
. Potrzebujesz go do porównywania obiektów, aby np. Skorzystać z metody sortowania ArrayList
klasy. Potrzebujesz sposobu na porównanie obiektów, aby móc je sortować. Potrzebujesz więc niestandardowej compareTo()
metody w swojej klasie, aby móc jej używać z ArrayList
metodą sort. Te compareTo()
powroty metoda -1,0,1.
Właśnie przeczytałem odpowiedni rozdział w Java Head 2.0, wciąż się uczę.
OK, ale dlaczego po prostu nie zdefiniować compareTo()
metody bez implementacji porównywalnego interfejsu. Na przykład klasa City
zdefiniowana przez jego name
i temperature
i
public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}