Hallo,
warum liefert mir der zweite assert false statt true? Ich komm einfach nicht dahinter. Hab schon die API zu awt.Point gelesen, also equals und hashcode würden eigentlich passend overriden, klappt aber nicht.
Hier der Code:
ich hab das gerade ausprobiert und komm zum selben Ergebnis und musste mich auch ein wenig wundern
Meine Vermutung ist folgende:
Das HashSet speichert seine Elemente in einer HashMap, wobei dann das Element (der Point) als key gespeichert wird.
Das Ganze dient der Eindeutigkeit, da man ja in einem HashSet kein Element doppelt speichern kann.
Und ich vermute mal, dass das irgendwie damit zusammenhängt.
Eine genauere Erklärung würde mich auch interessieren
ich hab gerade eine passgenaue und leicht verständliche Erklärung und Lösung "in diesem Internet" für das Problem gefunden:
Die Ursache des Problems liegt in der Referenz-Semantik von Java. Der Benutzer bekommt über die Referenzen Schreib-Zugriff auf die Objekte im Container und kann die dort abgelegten Objekte an Ort und Stelle verändern. Jede Veränderung der Objekte, die das Ergebnis von hashCode()beeinflusst, zerstört aber den Container, weil das Objekt nach der Veränderung eigentlich in einem anderen Bucket abgelegt sein müsste. Das ist ein generelles Problem bei allen Containern, deren Organisation in irgendeiner Form auf dem Inhalt der gespeicherten Objekten beruht und bei denen Schreib-Zugriff auf die gespeicherten Objekte möglich ist. In diese Kategorie fallen alle hash-basierten, aber auch alle baum-basierten Container in Java. Schützen kann man sich vor dieser Falle nur durch Programmierdisziplin, indem man es unterlässt, enthaltene Objekte an Ort und Stelle im Container zu ändern. Man muss statt dessen das alte Objekte aus dem Container entfernen und das neue "modifizierte" Objekt in den Container einfügen.
Danke euch für die Mithilfe. Aber von der Laufzeit oder Rechenaufwand scheint mir das ja mega-overheadbelastet zu sein, bei jeder Prüfung das zu ändernde Objekt entfernen und mit neuen Daten wieder adden...also ich programmiere gerade ein 2D-Spiel, wo auf jeden Tastendruck beim Steuern und bei jedem Timerrefresh jede Sekunde mehrfach auf contains geprüft wird...da wird das Programm ja nichtmehr fertig mit der Objekt-Schieberei...ich könnte mir gut vorstellen, dass das in C++ effektiever geht, oder?
Möglicherweise würde es in c++ effektiver laufen, das setzt aber auch voraus, dass du c++ gut beherrschst.
Warum nimmst du statt eines Sets nicht einfach eine Liste. Weil du keine doppelten Einträge haben willst ?
genau, weil ich keine doppelten Einträge wollte...also ich bilde ein Spielbrett ab, das 20 Reihen und 20 Spalten hat. Auf jedem Platz kann entweder ein Player, Enemy oder Obstacle stehen. Ursprünglich hatte ich das ganz simpel und lowlevel mit einem 2-dimensionalen int-Array gelöst. Aber da hat es mich genervt, dieses ewige Index +1/-1 für up-down-left-right move und check. Das fand ich total unleserlich, trotzdem dass ich Helpermethoden gebaut habe. Da hast du dann irgendwann keinen Bock mehr in deinem Code weiterzubauen, weil du dich jedesmal erst reindenken musst. Darum wollte ich jetzt eine komplett neue Version bauen wo Lesbarkeit des Codes oberste Priorität hat, weil das auch die Wartbarkeit und Änderbarkeit verbessert mit Objektorientierung.
Momentan überleg ich, es mit einem 2-dimensionalen ArrayList nochmal zu versuchen. Da ist ja per 2er-Index auch Eindeutigkeit gegeben und hab trotzdem die Bequemlichkeit des Collection-Frameworks und OO.
Mit C++ hab ich seit Jahren nix mehr gemacht. Aber das Grundproblem der Hashindexierung besteht bestimmt auch in C++, also geht es wohl eher darum die passendste Datenstruktur für meinen Anwendungsfall zu finden, wohl als Kompromiss aus Effektivität und Wartbarkeit. Und da kann ich dann schon bei Java bleiben.
Bitte genau trennen:
Du darfst durchaus mehrfach prüfen, ob ein Objekt in dem HashSet enthalten ist.
Du darfst es nur nicht (während es enthalten ist) verändern - dafür muss es erst entnommen werden, dann kannst du es ändern, und anschließend wieder einfügen.
(Außerdem - ist denn sicher, dass es immernoch "einmalig" ist, wenn es verändert wurde?)
also wenn ich mir das so überlege, ist es ja eigentlich garnicht so viel Rechenzeit, die da verbraten wird, es werden ja keine neuen Objekte erstellt, sondern nur die Referenzen hin und hergeschubst. Ich bau das jetz mal so ein, also erst remove, dann setlocation und dann wieder adden. Spiele sind nunmal an sich mit einem gewissen Rechenaufwand verbunden, da kommt man nicht drumrum. Und ich hab ja auch nicht vor es auf einem Embeded System laufen zu lassen...wobei diese Dinger heute ja auch schon enorme Power haben und sowas mit Links schaffen.
ja aber gerade das sind die Werte die ich ändern muss, die x und y Koordinaten. Das ist ja der Sinn der Sache beim moven der Tiles im Spielfeld. So wie ichs vorhin geschrieben habe, passt jetz alles. Alles rodscha in Kambodscha.
Oder hab ich dich irgendwie falsch verstanden?