Warum wird Java Comparable
verwendet? Warum sollte jemand Comparable
in einer Klasse implementieren ? Was ist ein reales Beispiel, bei dem Sie vergleichbare implementieren müssen?
Warum wird Java Comparable
verwendet? Warum sollte jemand Comparable
in einer Klasse implementieren ? Was ist ein reales Beispiel, bei dem Sie vergleichbare implementieren müssen?
Antworten:
Hier ist ein Beispiel aus dem wirklichen Leben. Beachten Sie, dass String
auch implementiert 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;
}
}
später..
/**
* 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
?
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 = new TreeSet<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:
public class District {
String zipcode;
Double populationDensity;
}
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:
public class District implements Comparable<District>{
String zipcode;
Double populationDensity;
public int compareTo(District other)
{
return populationDensity.compareTo(other.populationDensity);
}
}
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.
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?
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.
Edit: ..und machte das wichtige Stück fett.
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).
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:
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;
}
}
Eine einfache Möglichkeit, mehrere Feldvergleiche zu implementieren, ist Guavas ComparisonChain - dann können Sie sagen
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(lastName, that.lastName)
.compare(firstName, that.firstName)
.compare(zipCode, that.zipCode)
.result();
}
anstatt
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);
}
}
Zum Beispiel, wenn Sie eine sortierte Sammlung oder Karte haben möchten
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: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
Klasse: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
*/
}
}
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
Wenn Sie die Comparable
Schnittstelle implementieren , müssen Sie die Methode implementieren compareTo()
. Sie benötigen es, um Objekte zu vergleichen, um beispielsweise die Sortiermethode der ArrayList
Klasse 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 ArrayList
Sortiermethode 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, City
die durch ihre name
und temperature
und definiert ist
public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}