Der Fehler müsste sein, dass ich einmal List-contains brauche, was auf equals() basiert, und einmal Set-contains, was auf hashCode() und equals() basiert, mit unterschiedlichen Kriterien, und das unvereinbar ist. Ich nehm beide Methoden zum Vergleichen von Kanten aus, und mache das komplett anders…
schreiben. Ein bißchen aufpassen muss man trotzdem. Wenn die Kanten noch Informationen enthalten, die darüber hinausgehen, kann das unerwartete Effekte haben.
Was du zunächst erstmal brauchst, ist Nachhilfe in Hashcode-Equals-Konventionen.
Equals prüft Objekte auf inhaltliche Gleichheit. Identische Objekte sind ganz sicher auch vom Inhalt her gleich.
Ein Hashcode wird über den genau jenen Inhalt errechnet, der in Equals für die Prüfung verwendet wird. Da es meistens theoretisch weit mehr als 2^32 Instanzen einer Klasse geben kann, gilt, dass zwei Objekte ganz sicher inhaltlich ungleich sind, wenn ihr Hashcode unterschiedlich ist, jedoch auch dann noch unterschiedlich sein können, wenn sie den selben Hashcode haben.
Eine Lektion, die ich damals auch nicht gleich verstanden habe, als ich Code postete, in welchem ich „hashCode()“ in „equals()“ verwendete… Das geht ja mal gar nicht!
Dein Fehler ist zwar ein Anderer aber auch dieser hat mit oben genannten Konventionen zu tun. In der Klasse Kant errechnest du den Hashcode aus den beiden Knoten und prüfst in Equals dann nur k3.c.
Warum eine Kante bei dir 3 Knoten hat, weißt wahrscheinlich auch nur du - Eine Kante ist afaik die Verbindung zwischen nicht mehr als zwei Knoten.
Die Konvention, dass k1.c < k2.c zu sein hat, ist durchaus legitim, nur sollte man es auch dabei belassen. Das bedeutet k3 ist ohnehin überflüssig.
Wenn du nun immernoch eine Contains-Methode auf Ident-Basis benötigts, kannst du dir diese auch in einer erweiterten LinkedList implementieren, aber ich denke mal, das wird überflüssig, wenn du dich an die Hashcode-Equals-Konventionen hälst.
Irgendwo steckt ein Denkfehler…
Es gibt jetzt nur noch k1 und k2 (k3 war ja k2)…
Und sortiert sind die Kanten (sorry, Knoten) auch nicht…
Anwendung:
if (!k1.n.contains(new Kant(k1, k2, -1))) { } // soll true sein, wenn k1->k2 oder k2->k1 nicht enthalten ist
for (Knot knot : knots) {
for (Kant kant : knot.n) {
if (!kants.contains(kant)) { // kants ist Set; soll true sein,
// wenn kant.k1->kant.k2 oder kant.k2->kant.k1 nicht enthalten ist
kants.add(kant);
Sprachlich ist das etwas schwer. Gegeben sei k1 und k2. Wenn k1->k2 enthalten ist, dann soll contains true liefern. Wenn k2->k1 enthalten ist, dann soll contains true liefern.
Hieße verneint, dass beide oder keins von beiden enthalten sind?
Wieso machst du es dir so schwer? Wenn du bei der Instanzierung von Kant-Objekten stets darauf achtest, dass Knot 1 kleiner Knot 2 ist, wird es keine Kanten geben, bei denen Knot 1 größer Knot 2 ist und folglich können solche Kanten auch nicht in irgend einer Collection landen. Ein diesbezüglicher Test (siehe Post von Marco13) sollte zeigen, dass ein Test auf Knot 1 größer Knot 2 innerhalb einer Contains-Methode vollkommen überflüssig sind.
Es lag wahrscheinlich daran: Gegeben sein a->b und b->a. Set-contains findet bei b->a eine Hashkollision (a->b wurde vorher eingefügt), DANACH sagte equals aber: Ne, b->a ist ungleich a->b, und diese Kante wurde (in denselben bucket) eingefügt.
Das Thema darf als gelöst betrachtet werden. Aber wem gebührt jetzt die Ehre, es gelöst zu habn? TMII lag nicht falsch, Marco hatte den richtigen Code, Spacerat hat es super erklärt…
Marco hatte als erster den richtigen Code… Ihm gebührt die Ehre. Falls falsch, bitte umändern.