Ich habe also schon seit einiger Zeit mit einem Problem zu kämpfen, dachte, ich könnte hier genauso gut um Hilfe bitten.
Ich füge Ticketobjekte zu einem TreeSet hinzu, Ticket implementiert Comparable und hat die Methoden equals (), hashCode () und CompareTo () überschrieben. Ich muss überprüfen, ob ein Objekt bereits im TreeSet ist, indem ich contains () verwende. Jetzt nach dem Hinzufügen von 2 Elementen zum Set ist alles in Ordnung, aber nach dem Hinzufügen eines dritten wird es vermasselt.
Nach dem Hinzufügen eines dritten Elements zum TreeSet wird dieses kleine Stück Code ausgeführt. Ticket temp2 ist das Objekt, nach dem ich suche (verkoopLijst).
%Vor%gibt das zurück:
%Vor%Nun wäre meine Frage, wie das überhaupt möglich ist?
Bearbeiten:
%Vor%compareTo
Vertrag Das Problem liegt in Ihrem compareTo
. Hier ein Auszug aus der Dokumentation :
Der Implementierer muss
sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
für allex
undy
sicherstellen.
Ihr ursprünglicher Code wird hier als Referenz reproduziert:
%Vor% Warum ist der return 1;
ein Fehler? Stellen Sie sich das folgende Szenario vor:
Ticket t1, t2
t1.boeking.compareTo(t2.boeking) == 0
t1.equals(t2)
return false
t1.compareTo(t2)
gibt 1
zurück
t2.compareTo(t1)
gibt 1
zurück
Diese letzte Konsequenz ist eine Verletzung des compareTo
Vertrags.
In erster Linie sollten Sie die Tatsache ausgenutzt haben, dass Comparable<T>
ein parametrisierbarer generischer Typ ist. Das heißt statt:
es wäre viel angemessener, stattdessen etwas wie das zu deklarieren:
%Vor% Jetzt können wir unsere compareTo(Ticket)
(nicht mehr compareTo(Object)
) schreiben. Es gibt viele Möglichkeiten, dies umzuschreiben, aber hier ist eine ziemlich einfache, die funktioniert:
Nun können wir auch equals(Object)
in compareTo(Ticket)
definieren anstatt umgekehrt:
Beachten Sie die Struktur von compareTo
: Sie enthält mehrere return
-Anweisungen, aber der Fluss der Logik ist tatsächlich gut lesbar. Beachten Sie auch, dass die Priorität der Sortierkriterien explizit und leicht umsortierbar ist, wenn Sie unterschiedliche Prioritäten berücksichtigen.
Dies kann passieren, wenn Ihre compareTo-Methode nicht konsistent ist. I.e. Wenn a.compareTo(b) > 0
, dann muss b.compareTo(a)
& lt sein; 0. Und wenn a.compareTo(b) > 0
und b.compareTo(c) > 0
, dann muss a.compareTo(c)
& gt; 0. Wenn das nicht wahr ist, kann TreeSet alles durcheinander bringen.
Erstens: Wenn Sie TreeSet
verwenden, wirkt sich das tatsächliche Verhalten Ihrer hashCode
-Methoden nicht auf die Ergebnisse aus. TreeSet
ist nicht auf Hashing angewiesen.
Wirklich müssen wir mehr Code sehen; z.B. die tatsächlichen Implementierungen der Methoden equals
und compareTo
und der Code, der TreeSet
instanziiert.
Wenn ich jedoch raten sollte, wäre es überladen die Methode equals
, indem Sie sie mit der Signatur boolean equals(Ticket other)
deklarieren. Das würde zu dem Verhalten führen, das Sie sehen. Um das erforderliche Verhalten zu erhalten, müssen Sie die Methode überschreiben ; z.B.
(Es ist eine gute Idee, die Annotation @Override
einzufügen, um deutlich zu machen, dass die Methode eine Methode in der Oberklasse überschreibt oder eine Methode in einer Schnittstelle implementiert. Wenn Ihre Methode keine Überschreibung ist, dann Sie werden einen Kompilierungsfehler bekommen ... was eine gute Sache wäre.)
BEARBEITEN
Basierend auf dem Code, den Sie der Frage hinzugefügt haben, besteht das Problem nicht in Overload und Override. (Wie gesagt, ich habe nur geraten ...)
Es ist sehr wahrscheinlich, dass compareTo
und equals
falsch sind. Es ist noch nicht ganz klar, wo genau der Fehler liegt, da die Semantik beider Methoden von den Methoden compareTo
und equals
der Klasse Boeking
abhängt.
Die erste if-Anweisung von Ticket.compareTo
sieht sehr verdächtig aus. Es sieht so aus, als ob return 1;
t1.compareTo(t2)
und t2.compareTo(t1)
dazu bringen könnte 1
für einige Tickets t1
und t2
... zurückzugeben und das wäre definitiv falsch.