Gleich und vergleichbar mit Sets

8

Ich habe hier einen Code hier gepostet, der ein Problem, das das Poster hatte, richtig gelöst hat. OP wollte Duplikate entfernen und bestimmte Sonderelemente an die Spitze einer Liste bringen. Ich habe eine TreeSet mit einer speziellen Comparable -Klasse verwendet, die die Locale , mit denen sie gearbeitet haben, eingepackt hat, um zu erreichen, was sie wollten.

Ich habe dann gedacht ... wie du ... dass ich Duplikate eliminiere, indem ich 0 von der compareTo -Methode zurückbringe, nicht indem ich true von einer equals -Implementierung zurückgebe, wie es nötig wäre zu tun, um ein Duplikat in Set korrekt anzugeben (aus der Definition von Set ).

Ich habe nichts dagegen, diese Technik zu verwenden, aber verwende ich etwas, das als undokumentiertes Feature betrachtet werden könnte? Kann ich davon ausgehen, dass es auch weiterhin funktionieren wird, wenn man so etwas tut?

    
OldCurmudgeon 06.10.2012, 16:25
quelle

1 Antwort

17

Es scheint, dass dies in JavaDoc von TreeSet (fett meins):

  

Beachten Sie, dass die von einer Menge gepflegte Reihenfolge (unabhängig davon, ob ein expliziter Vergleicher angegeben wird) mit equals übereinstimmen muss, wenn die Schnittstelle Set korrekt implementiert werden soll. (Siehe Comparable oder Comparator für eine genaue Definition von konsistent mit equals.) Dies liegt daran, dass die Set -Schnittstelle als equals -Operation definiert ist, eine TreeSet -Instanz dagegen alle Elementvergleiche mit der Methode compareTo (oder compare) , so dass zwei Elemente, die mit dieser Methode als gleich angesehen werden, vom Standpunkt der Menge her gleich sind. Das Verhalten einer Menge ist wohldefiniert, auch wenn ihre Reihenfolge nicht mit gleich ist; Es entspricht nur nicht dem allgemeinen Vertrag der Set Schnittstelle .

Hier ist ein Beispiel für die einzige (?) JDK-Klasse das Comparable implementiert, aber nicht mit equals() übereinstimmt:

%Vor%

decimals am Ende haben drei Werte, weil 42 , 42.0 und 42.00 nicht gleich sind, solange equals() betroffen ist. Wenn Sie jedoch HashSet durch TreeSet ersetzen, enthält die resultierende Menge nur 1 Element ( 42 - das ist das erste, das hinzugefügt wurde), da alle verglichen werden, wenn Sie BigDecimal.compareTo() .

Dies zeigt, dass TreeSet gewissermaßen " kaputt " ist, wenn Typen verwendet werden, die nicht konsistent mit equals() sind. Es funktioniert immer noch richtig und alle Operationen sind gut definiert - es entspricht nicht dem Vertrag von Set class - wenn zwei Klassen nicht equal() sind, werden sie nicht als Duplikate betrachtet.

Siehe auch

Tomasz Nurkiewicz 06.10.2012, 16:36
quelle