Warum sollte eine Java-Klasse vergleichbar implementieren?
136
Warum wird Java Comparableverwendet? Warum sollte jemand Comparablein einer Klasse implementieren ? Was ist ein reales Beispiel, bei dem Sie vergleichbare implementieren müssen?
Hier ist ein Beispiel aus dem wirklichen Leben. Beachten Sie, dass Stringauch implementiert Comparable.
classAuthorimplementsComparable<Author>{String firstName;String lastName;@Overridepublicint 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 equalint last =this.lastName.compareTo(other.lastName);return last ==0?this.firstName.compareTo(other.firstName): last;}}
später..
/**
* List the authors. Sort them by name so it will look good.
*/publicList<Author> listAuthors(){List<Author> authors = readAuthorsFromFileOrSomething();Collections.sort(authors);return authors;}/**
* List unique authors. Sort them by name so it will look good.
*/publicSortedSet<Author> listUniqueAuthors(){List<Author> authors = readAuthorsFromFileOrSomething();returnnewTreeSet<Author>(authors);}
Ich möchte nur darauf hinweisen, dass Sie häufig überschreiben möchten equals(und daher hashCode), um mit Ihrer compareToMethode übereinzustimmen. Dies ist beispielsweise erforderlich, wenn die Klasse mit a gut spielen soll TreeSet.
Pidge
Warum nicht einfach zurückkehren last?
Anirban Nag 'tintinmj'
@ AnirbanNag'tintinmj ', um automatisch nach dem Vornamen zu sortieren, falls der Nachname identisch ist.
OddDev
Plus eins für die gute Erklärung, warum compareTo ein int zurückgibt und was es bedeutet. Am hilfreichsten.
James.garriss
1
@ user3932000: Richtig, das ist so ziemlich der Punkt aller Schnittstellen. Beachten Sie jedoch, dass "andere Java-Methoden" vom Benutzer geschriebene Methoden enthalten! Tatsächlich würde ich behaupten, dass die meisten Schnittstellen vom Code des Benutzers verwendet werden. In größeren Codebasen wird "Sie selbst" schnell zu "Anderen"
Enno Shioji
40
Vergleichbar definiert eine natürliche Ordnung. Dies bedeutet, dass Sie definieren, wann ein Objekt als "kleiner als" oder "größer als" betrachtet werden soll.
Angenommen, Sie haben eine Reihe von Ganzzahlen und möchten diese sortieren. Das ist ziemlich einfach, legen Sie sie einfach in eine sortierte Sammlung, oder?
TreeSet<Integer> m =newTreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);for(Integer i : m)...// values will be sorted
Angenommen, ich habe ein benutzerdefiniertes Objekt, bei dem das Sortieren für mich sinnvoll, aber nicht definiert ist. Angenommen, ich habe Daten, die Bezirke nach Postleitzahl mit Bevölkerungsdichte darstellen, und ich möchte sie nach Dichte sortieren:
Der einfachste Weg, sie zu sortieren, besteht darin, sie mit einer natürlichen Reihenfolge zu definieren, indem Comparable implementiert wird. Dies bedeutet, dass diese Objekte standardmäßig so angeordnet sind, dass sie geordnet werden:
Beachten Sie, dass Sie das Gleiche tun können, indem Sie einen Komparator definieren. Der Unterschied besteht darin, dass der Komparator die Ordnungslogik außerhalb des Objekts definiert . Vielleicht muss ich in einem separaten Prozess dieselben Objekte nach Postleitzahl bestellen - in diesem Fall ist die Reihenfolge nicht unbedingt eine Eigenschaft des Objekts oder unterscheidet sich von der natürlichen Reihenfolge der Objekte. Sie können einen externen Komparator verwenden, um eine benutzerdefinierte Reihenfolge für Ganzzahlen zu definieren, indem Sie sie beispielsweise nach ihrem alphabetischen Wert sortieren.
Grundsätzlich muss die Ordnungslogik irgendwo existieren. Das kann sein -
im Objekt selbst, wenn es natürlich vergleichbar ist (erweitert Comparable -eg Ganzzahlen)
Lieferung in einem externen Komparator, wie im obigen Beispiel.
gutes Beispiel, aber es muss TreeSet<Integer>stattdessen sein TreeMap<Integer>, dass TreeMaps immer <Key,Value>-paare sind, da letzteres nicht existiert . Übrigens TreeMap<District, Object>würde eine Hypothese nur funktionieren, wenn District Comparable implementiert hätte, oder?
Ich
14
Zitiert aus dem Javadoc;
Diese Schnittstelle legt den Objekten jeder Klasse, die sie implementiert, eine Gesamtreihenfolge auf. Diese Reihenfolge wird als natürliche Reihenfolge der Klasse bezeichnet, und die compareTo-Methode der Klasse wird als natürliche Vergleichsmethode bezeichnet.
Listen (und Arrays) von Objekten, die diese Schnittstelle implementieren, können automatisch nach Collections.sort (und Arrays.sort) sortiert werden. Objekte, die diese Schnittstelle implementieren, können als Schlüssel in einer sortierten Zuordnung oder als Elemente in einer sortierten Menge verwendet werden, ohne dass ein Komparator angegeben werden muss.
Ich würde sagen, dass der Satz nach dem, den Sie fett gedruckt haben, genauso wichtig ist (wenn nicht sogar wichtiger).
Michael Borgwardt
8
Die Tatsache, dass eine Klasse implementiert, Comparablebedeutet, dass Sie zwei Objekte aus dieser Klasse nehmen und vergleichen können. Einige Klassen, wie bestimmte Sammlungen (Sortierfunktion in einer Sammlung), die Objekte in Ordnung halten, setzen voraus, dass sie vergleichbar sind (um zu sortieren, müssen Sie wissen, welches Objekt das "größte" ist und so weiter).
Die meisten der obigen Beispiele zeigen, wie ein vorhandenes vergleichbares Objekt in der Funktion compareTo wiederverwendet wird. Wenn Sie Ihren eigenen compareTo implementieren möchten, wenn Sie zwei Objekte derselben Klasse vergleichen möchten, sagen Sie ein AirlineTicket-Objekt, das Sie nach Preis sortieren möchten (weniger steht an erster Stelle), gefolgt von der Anzahl der Zwischenstopps (wiederum ist weniger) Rang 1), würden Sie Folgendes tun:
classAirlineTicketimplementsComparable<Cost>{publicdouble cost;publicint stopovers;publicAirlineTicket(double cost,int stopovers){this.cost = cost;this.stopovers = stopovers ;}publicint compareTo(Cost o){if(this.cost != o.cost)returnDouble.compare(this.cost, o.cost);//sorting in ascending order. if(this.stopovers != o.stopovers)returnthis.stopovers - o.stopovers;//again, ascending but swap the two if you want descendingreturn0;}}
Fernando bedeutet: Wenn Sie "Dinge", die Comparable implementieren, in einer sortierten Containerklasse speichern, kann die sortierte Containerklasse diese "Dinge" automatisch bestellen.
Ian Durkan
2
Vergleichbar wird verwendet, um Instanzen Ihrer Klasse zu vergleichen. Wir können Instanzen auf viele Arten vergleichen, deshalb müssen wir eine Methode implementieren, compareToum zu wissen, wie (Attribute) wir Instanzen vergleichen möchten.
Dog Klasse:
package test;import java.util.Arrays;publicclassMain{publicstaticvoid main(String[] args){Dog d1 =newDog("brutus");Dog d2 =newDog("medor");Dog d3 =newDog("ara");Dog[] dogs =newDog[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 Klasse:
package test;import java.util.Arrays;publicclassMain{publicstaticvoid main(String[] args){Dog d1 =newDog("brutus");Dog d2 =newDog("medor");Dog d3 =newDog("ara");Dog[] dogs =newDog[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
*/}}
Hier ist ein gutes Beispiel für die Verwendung von vergleichbaren in Java:
Wenn Sie die ComparableSchnittstelle implementieren , müssen Sie die Methode implementieren compareTo(). Sie benötigen es, um Objekte zu vergleichen, um beispielsweise die Sortiermethode der ArrayListKlasse zu verwenden. Sie benötigen eine Möglichkeit, Ihre Objekte zu vergleichen, um sie sortieren zu können. Sie benötigen also eine benutzerdefinierte compareTo()Methode in Ihrer Klasse, damit Sie sie mit der ArrayListSortiermethode verwenden können. Die compareTo()Methode gibt -1,0,1 zurück.
Ich habe gerade ein entsprechendes Kapitel in Java Head 2.0 gelesen und lerne noch.
OK, aber warum nicht einfach eine compareTo()Methode definieren , ohne eine vergleichbare Schnittstelle zu implementieren? Zum Beispiel eine Klasse, Citydie durch ihre nameund temperatureund definiert ist
Antworten:
Hier ist ein Beispiel aus dem wirklichen Leben. Beachten Sie, dass
String
auch implementiertComparable
.später..
quelle
equals
(und daherhashCode
), um mit IhrercompareTo
Methode übereinzustimmen. Dies ist beispielsweise erforderlich, wenn die Klasse mit a gut spielen sollTreeSet
.last
?Vergleichbar definiert eine natürliche Ordnung. Dies bedeutet, dass Sie definieren, wann ein Objekt als "kleiner als" oder "größer als" betrachtet werden soll.
Angenommen, Sie haben eine Reihe von Ganzzahlen und möchten diese sortieren. Das ist ziemlich einfach, legen Sie sie einfach in eine sortierte Sammlung, oder?
Angenommen, ich habe ein benutzerdefiniertes Objekt, bei dem das Sortieren für mich sinnvoll, aber nicht definiert ist. Angenommen, ich habe Daten, die Bezirke nach Postleitzahl mit Bevölkerungsdichte darstellen, und ich möchte sie nach Dichte sortieren:
Der einfachste Weg, sie zu sortieren, besteht darin, sie mit einer natürlichen Reihenfolge zu definieren, indem Comparable implementiert wird. Dies bedeutet, dass diese Objekte standardmäßig so angeordnet sind, dass sie geordnet werden:
Beachten Sie, dass Sie das Gleiche tun können, indem Sie einen Komparator definieren. Der Unterschied besteht darin, dass der Komparator die Ordnungslogik außerhalb des Objekts definiert . Vielleicht muss ich in einem separaten Prozess dieselben Objekte nach Postleitzahl bestellen - in diesem Fall ist die Reihenfolge nicht unbedingt eine Eigenschaft des Objekts oder unterscheidet sich von der natürlichen Reihenfolge der Objekte. Sie können einen externen Komparator verwenden, um eine benutzerdefinierte Reihenfolge für Ganzzahlen zu definieren, indem Sie sie beispielsweise nach ihrem alphabetischen Wert sortieren.
Grundsätzlich muss die Ordnungslogik irgendwo existieren. Das kann sein -
im Objekt selbst, wenn es natürlich vergleichbar ist (erweitert Comparable -eg Ganzzahlen)
Lieferung in einem externen Komparator, wie im obigen Beispiel.
quelle
TreeSet<Integer>
stattdessen seinTreeMap<Integer>
, dass TreeMaps immer<Key,Value>
-paare sind, da letzteres nicht existiert . ÜbrigensTreeMap<District, Object>
würde eine Hypothese nur funktionieren, wenn District Comparable implementiert hätte, oder?Zitiert aus dem Javadoc;
Edit: ..und machte das wichtige Stück fett.
quelle
Die Tatsache, dass eine Klasse implementiert,
Comparable
bedeutet, dass Sie zwei Objekte aus dieser Klasse nehmen und vergleichen können. Einige Klassen, wie bestimmte Sammlungen (Sortierfunktion in einer Sammlung), die Objekte in Ordnung halten, setzen voraus, dass sie vergleichbar sind (um zu sortieren, müssen Sie wissen, welches Objekt das "größte" ist und so weiter).quelle
Die meisten der obigen Beispiele zeigen, wie ein vorhandenes vergleichbares Objekt in der Funktion compareTo wiederverwendet wird. Wenn Sie Ihren eigenen compareTo implementieren möchten, wenn Sie zwei Objekte derselben Klasse vergleichen möchten, sagen Sie ein AirlineTicket-Objekt, das Sie nach Preis sortieren möchten (weniger steht an erster Stelle), gefolgt von der Anzahl der Zwischenstopps (wiederum ist weniger) Rang 1), würden Sie Folgendes tun:
quelle
Eine einfache Möglichkeit, mehrere Feldvergleiche zu implementieren, ist Guavas ComparisonChain - dann können Sie sagen
anstatt
quelle
Zum Beispiel, wenn Sie eine sortierte Sammlung oder Karte haben möchten
quelle
Vergleichbar wird verwendet, um Instanzen Ihrer Klasse zu vergleichen. Wir können Instanzen auf viele Arten vergleichen, deshalb müssen wir eine Methode implementieren,
compareTo
um zu wissen, wie (Attribute) wir Instanzen vergleichen möchten.Dog
Klasse:Main
Klasse:Hier ist ein gutes Beispiel für die Verwendung von vergleichbaren in Java:
http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2
quelle
Wenn Sie die
Comparable
Schnittstelle implementieren , müssen Sie die Methode implementierencompareTo()
. Sie benötigen es, um Objekte zu vergleichen, um beispielsweise die Sortiermethode derArrayList
Klasse zu verwenden. Sie benötigen eine Möglichkeit, Ihre Objekte zu vergleichen, um sie sortieren zu können. Sie benötigen also eine benutzerdefiniertecompareTo()
Methode in Ihrer Klasse, damit Sie sie mit derArrayList
Sortiermethode verwenden können. DiecompareTo()
Methode gibt -1,0,1 zurück.Ich habe gerade ein entsprechendes Kapitel in Java Head 2.0 gelesen und lerne noch.
quelle
OK, aber warum nicht einfach eine
compareTo()
Methode definieren , ohne eine vergleichbare Schnittstelle zu implementieren? Zum Beispiel eine Klasse,City
die durch ihrename
undtemperature
und definiert istquelle