Wann sollte eine Klasse vergleichbar und / oder vergleichend sein?


138

Ich habe Klassen gesehen, die sowohl Comparable als auch Comparator implementieren . Was bedeutet das? Warum sollte ich eins über das andere verwenden?


18
Hast du den Javadoc darüber gelesen? Es beschreibt den Unterschied ganz klar.
Skaffman

1
Was ist vergleichbar und Vergleich und wann ist vergleichbar und Vergleich zu verwenden. Um diese zu kennen, lesen Sie diesen Link. Dies wird Ihnen helfen, ihr Verhalten und ihre Verwendung zu verstehen. http://iandjava.blogspot.in/2012/10/comparable-and-comparator.html
RockStar

6
Dies ist eine gute Frage mit einer guten, objektiven Antwort. Ich bin bestürzt, dass es geschlossen ist.
Russell Silva

3
Andere Fragen zu StackOverflow beziehen sich auf die endgültige Frage "Was ist der Unterschied zwischen Komparator und Vergleichbar?". Warum ist es als "nicht konstruktiv" gekennzeichnet? Als Java-Neuling war dies eine sehr nützliche Frage!
Pete

Antworten:


241

Der folgende Text stammt von Comparator vs Comparable

Vergleichbar

Ein vergleichbares Objekt kann sich mit einem anderen Objekt vergleichen. Die Klasse selbst muss die java.lang.ComparableSchnittstelle implementieren , um ihre Instanzen vergleichen zu können.

Komparator

Ein Komparatorobjekt kann zwei verschiedene Objekte vergleichen. Die Klasse vergleicht nicht ihre Instanzen, sondern die Instanzen einiger anderer Klassen. Diese Komparatorklasse muss die java.util.ComparatorSchnittstelle implementieren .


Für eine detaillierte Erklärung der Verwendung von Comparator und vergleichbaren: sysdotoutdotprint.com/index.php/2017/03/28/…
mel3kings

2
Ein weiterer guter Artikel: codecramp.com/java-comparable-vs-comparator
EMM

@ mel3kings - Link ist nicht mehr zugänglich.
Gaurav

152

Implementieren Comparablebedeutet " Ich kann mich mit einem anderen Objekt vergleichen ". Dies ist normalerweise nützlich, wenn es einen einzelnen natürlichen Standardvergleich gibt.

Implementieren Comparatorbedeutet " Ich kann zwei andere Objekte vergleichen ". Dies ist normalerweise nützlich, wenn es mehrere Möglichkeiten gibt, zwei Instanzen eines Typs zu vergleichen - z. B. können Sie Personen nach Alter, Name usw. vergleichen.


1
Hallo Skeet, können Sie bitte den Code mit vergleichbar und Komparator löschen.
Mdhar9e

5
@ mdhar9e: Es gibt viele Beispiele. Wenn Sie Schwierigkeiten haben, sie in Ihr spezifisches Szenario zu übersetzen, geben Sie in einer neuen Frage weitere Informationen an.
Jon Skeet

2
@alireza: Ich habe bereits im zweiten Absatz ein Beispiel gegeben: Wenn Sie verschiedene Komparatoren haben, können Sie dieselbe Sammlung (Personen) nach verschiedenen Eigenschaften (Alter, Name usw.) sortieren. Sie können dies nicht einfach durch PersonImplementieren tun Comparable, da Sie dann nicht ändern können, wie zwei Personen verglichen werden.
Jon Skeet

1
@feelgoodandprogramming: Nein, sind die verschiedenen Sortieralgorithmen . Hier gibt es möglicherweise drei Codeteile in drei verschiedenen Klassen: 1) Die Entität selbst, z Person. 2) Der Komparator, der beispielsweise PersonAgeComparatorzwei verschiedene Entitäten vergleichen und entscheiden kann, welche in dieser bestimmten Sortierreihenfolge an erster Stelle stehen sollen. 3) Der Sortiercode, der eine Sammlung von Entitäten und einen Komparator verwendet und diese Sammlung mithilfe des Komparators sortiert, um die Reihenfolge zu bestimmen.
Jon Skeet

2
@RishiKeshPathak: Nun, es ist mehr, dass Sie Comparable verwenden, wenn es nur eine einzige offensichtliche Sache gibt, mit der Sie vergleichen können. Und selbst dann Sie können nur Vergleicher schreiben. Wenn Sie zwei verschiedene Programme mit derselben Klasse haben und eines nach Alter und das andere nach Namen sortieren möchte, muss mindestens eines einen Komparator verwenden.
Jon Skeet

38

Mit Comparable kann eine Klasse ihren eigenen Vergleich implementieren:

  • es ist in der gleichen Klasse (es ist oft ein Vorteil)
  • Es kann nur eine Implementierung geben (Sie können diese also nicht verwenden, wenn Sie zwei verschiedene Fälle wünschen).

Im Vergleich dazu ist Comparator ein externer Vergleich:

  • Es befindet sich normalerweise in einer eindeutigen Instanz (entweder in derselben Klasse oder an einem anderen Ort).
  • Sie benennen jede Implementierung wie Sie die Dinge sortieren möchten
  • Sie können Komparatoren für Klassen bereitstellen , die Sie nicht steuern
  • Die Implementierung ist auch dann verwendbar, wenn das erste Objekt null ist

In beiden Implementierungen können Sie weiterhin auswählen, was Sie vergleichen möchten . Mit Generika können Sie dies deklarieren und zur Kompilierungszeit überprüfen lassen. Dies verbessert die Sicherheit, ist aber auch eine Herausforderung, den geeigneten Wert zu bestimmen.

Als Richtlinie verwende ich im Allgemeinen die allgemeinste Klasse oder Schnittstelle, mit der dieses Objekt verglichen werden kann, in allen Anwendungsfällen, die ich mir vorstelle ... Eine Definition ist jedoch nicht sehr genau! :-(

  • Comparable<Object>Sie können es zur Kompilierungszeit in allen Codes verwenden (was bei Bedarf gut oder wenn nicht schlecht ist und Sie den Fehler bei der Kompilierung verlieren). Ihre Implementierung muss mit Objekten umgehen und nach Bedarf, aber auf robuste Weise gegossen werden.
  • Comparable<Itself> ist im Gegenteil sehr streng.

Komisch, wenn Sie sich selbst der Unterklasse unterordnen, muss die Unterklasse auch vergleichbar und robust sein (sonst würde das Liskov-Prinzip brechen und Ihnen Laufzeitfehler geben).


20

java.lang.Comparable

  1. Um die ComparableSchnittstelle zu implementieren , muss die Klasse eine einzelne Methode implementierencompareTo()

    int a.compareTo(b)

  2. Sie müssen die Klasse ändern, deren Instanz Sie sortieren möchten. Damit kann nur eine Sortierfolge pro Klasse erstellt werden.

java.util.Comparator

  1. Um die Comparator-Schnittstelle zu implementieren, muss die Klasse eine einzelne Methode implementieren compare()

    int compare (a,b)

  2. Sie erstellen eine Klasse getrennt von der Klasse, deren Instanz Sie sortieren möchten. Damit können mehrere Sortierfolgen pro Klasse erstellt werden.

14

Comparable dient zum Bereitstellen einer Standardreihenfolge für Datenobjekte, z. B. wenn die Datenobjekte eine natürliche Reihenfolge haben.

A Comparatorrepräsentiert die Bestellung selbst für eine bestimmte Verwendung.


8

Comparablewird normalerweise bevorzugt. Aber manchmal implementiert eine Klasse bereits Comparable, aber Sie möchten nach einer anderen Eigenschaft sortieren. Dann müssen Sie a verwenden Comparator.

Einige Klassen sehen tatsächlich Comparatorshäufige Fälle vor; Zum Beispiel wird Stringbei der Sortierung standardmäßig zwischen Groß- und Kleinschreibung unterschieden, es wird jedoch auch eine statische Aufforderung Comparatoraufgerufen CASE_INSENSITIVE_ORDER.


7
Ich bin mir nicht sicher, ob ich damit einverstanden bin, dass Comparable bevorzugt wird. Einige Objekte haben einen starken Sinn für natürliche Ordnung - nämlich Zahlen in all ihren Formen: natürliche Zahlen, reelle Zahlen, Daten usw. Aber auch anderen relativ primitiven Objekten wie Zeichenketten fehlt eine universell anwendbare Ordnung. Bei komplexeren Objekten wie einer Entität aus einem Anwendungsdomänenmodell ist die Implementierung von Comparable normalerweise ein Fehler. Ihre vielen Eigenschaften machen es zu schwierig, vorherzusagen, welche Reihenfolge am häufigsten gewünscht wird.
erickson

6

Hier sind einige Unterschiede zwischen Comparator und Comparable, die ich im Web gefunden habe:

  1. Wenn Sie sehen, dass der logische Unterschied zwischen diesen beiden darin besteht, dass Comparator in Java zwei ihm zur Verfügung gestellte Objekte vergleicht, während die Comparable-Schnittstelle "diese" Referenz mit dem angegebenen Objekt vergleicht.

  2. In Java vergleichbar wird verwendet, um die natürliche Reihenfolge von Objekten zu implementieren. In Java API String implementieren Date- und Wrapper-Klassen eine vergleichbare Schnittstelle.

  3. Wenn eine Klasse eine vergleichbare Schnittstelle in Java implementiert, kann die Sammlung dieses Objekts, entweder List oder Array, automatisch mithilfe der Collections.sort () - oder Array.sort () -Methode sortiert werden, und das Objekt wird basierend auf der durch die CompareTo-Methode definierten natürlichen Reihenfolge sortiert.

  4. Objekte, die Comparable in Java implementieren, können als Schlüssel in einer sortierten Map oder als Elemente in einer sortierten Gruppe verwendet werden, z. B. TreeSet, ohne einen Comparator anzugeben.

site: Wie verwende ich Comparator und Comparable in Java? Mit Beispiel

Lesen Sie mehr: Wie verwende ich Comparator und Comparable in Java? Mit Beispiel


5

Comparableist für Objekte mit einer natürlichen Ordnung. Das Objekt selbst weiß, wie es bestellt werden soll.
Comparatorist für Objekte ohne natürliche Reihenfolge oder wenn Sie eine andere Reihenfolge verwenden möchten.


4

Unterschied zwischen Komparator- und vergleichbaren Schnittstellen

Comparable wird verwendet, um sich selbst mit einem anderen Objekt zu vergleichen.

Comparator wird verwendet, um zwei Datentypen zu vergleichen, die Objekte sind.


2

Wenn Sie sehen, dass der logische Unterschied zwischen diesen beiden Comparatorin Java besteht, vergleichen Sie zwei ihm bereitgestellte Objekte, während die ComparableSchnittstelle "diese" Referenz mit dem angegebenen Objekt vergleicht.

Comparablein Java wird verwendet, um die natürliche Reihenfolge von Objekten zu implementieren. In Java API implementieren String-, Date- und Wrapper-Klassen die ComparableSchnittstelle.

Wenn eine Klasse eine ComparableSchnittstelle in Java implementiert , wird die Sammlung dieses Objekts entweder Listoder Arraymithilfe von Collections.sort()oder Array.sort()Methode und Objekt automatisch sortiert, basierend auf der durch die compareToMethode definierten natürlichen Reihenfolge .

Objekte, die Comparablein Java implementiert werden, können beispielsweise als Schlüssel in einer sortierten Zuordnung oder als Elemente in einer sortierten Menge verwendet werden TreeSet, ohne dass dies angegeben wird Comparator.


0

Meine Annotation lib zur Implementierung von Comparable und Comparator:

public class Person implements Comparable<Person> {         
    private String firstName;  
    private String lastName;         
    private int age;         
    private char gentle;         

    @Override         
    @CompaProperties({ @CompaProperty(property = "lastName"),              
        @CompaProperty(property = "age",  order = Order.DSC) })           
    public int compareTo(Person person) {                 
        return Compamatic.doComparasion(this, person);         
    }  
} 

Klicken Sie auf den Link, um weitere Beispiele anzuzeigen. compamatic


3
Willkommen bei stackoverflow. Diese Frage ist alt und wurde bereits beantwortet. In der Regel ist es am besten, veraltete Threads nicht wiederzubeleben, es sei denn, Ihre Antwort trägt etwas wesentlich Neues oder Anderes gegenüber früheren Antworten bei.
Oers
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.