HashMap - put() reagiert nicht?

  • Themenstarter Themenstarter Masterand
  • Beginndatum Beginndatum
M

Masterand

Gast
Hallo Miteinander,
ich schreibe an einem etwas umfangreicheren Projekt (Abschlussarbeit, bin aber kein Informatiker) und habe auch schon das eine oder andere programmiert. Da es aber "nur" um HashMap put() geht muss ich mich wohl bei den Anfängerthemen einreihen...

Folgender Code:

Java:
ladeflaechen ist HashMap<Ladeflaeche,ULD>
lf ist Ladeflaeche
coordULD.uld ist ULD (bzw erbt von ULD)

Schleife,IF usw{
ladeflaechen.put(lf,coordULD.uld);
System.out.println("Ja, "+lf+" vorhanden: "+ladeflaechen.keySet());
}

Ausgabe aus 2 Durchläufen (Code aussenrum und auch diese Schleife liefen schon sehr häufig, ladeflaechen ist frisch initialisiert)
Ja, 120,0,0:99880x1000 vorhanden: [120,0,0:99880x1000]

Ja, 0,100,0:120x900 vorhanden: [120,0,0:99880x1000]
Sonstige Erklärungen: Die Zahlenfolge der Ausgabe ist jeweils ein Element lf.toString() (für Interessierte: x,y,z:LängexBreite)

Warum fügt put() im zweiten Durchlauf nichts hinzu? Überschreiben gäbe es ja Ansatzpunkte für die Bugsuche, aber gar keine Veränderung?

Der Fehler tritt nur sehr selten auf (wenn, dann aber immer an fast der gleichen Stelle), deshalb ist auch kein Minimalbeispiel möglich. Sehr selten heißt: bei geschätzt über 1 Mio put() 6-8 Mal.

Gibt es irgendwelche logischen Erklärungen warum put zu keiner Veränderung führt? Weder google noch API haben mich weitergebracht. Vielleicht sehe ich auch den Wald vor lauter Bäumen nicht...

Gruß Mathias


PS: Obiges Beispiel ist natürlich zu wenig, um das Problem zu lösen. Mir reicht schon jeder Tip, wo ich bei der Bugsuche weitermachen kann. Auf diese beiden Zeilen habe ich es meiner Meinung nach eingegrenzt. - Ich bin für alles dankbar, auch wenn mir nur gezeigt wird, warum in der Eingrenzung nicht unbedingt ein Fehler liegen muss. Es können beliebige Annahmen getroffen werden, um das Phänomen zu erklären 😉
 
Java:
public int hashCode(){
	int result=0;
	result=x+laenge/2+1000*(y+breite/2)+1000000*z;
	return result;
}
	
public boolean equals(Object vergleich){
	if(vergleich.hashCode()!=hashCode()){
		return false;
	}
	if(vergleich.getClass()==this.getClass()){
		return true;
	}
	return false;
}


Meiner Meinung nach ja - aber selbst wenn nicht: Dann würde put() doch ersetzen, oder?

Aber: Es stimmt, als ich HashCode() geschrieben habe bin ich noch von Werten für x/y/z+laenge/breite<1000 ausgegangen, das stimmt hier nicht mehr...
Von Hand nachgerechnet: Die HashCodes sind unterschiedlich.
 
Nachtrag: Die Hash-Codes sind doch gleich.

Dann habe ich die API wohl falsch verstanden - ich dachte, er würde bei gleichem Hash-Code den alten Key rausschmeißen.

Problem ist damit vermutlich gelöst, ich ändere HashCode() und melde mich nochmal.
 
Aha, es müssen also nur hashCodes und Klassen gleich sein, schon sind beide Objekte gleich?

Falls deine IDE das kann, würde ich die mal equals und hashCode implementieren lassen, und noch mal versuchen.
 
Damit ist es gefunden - und mit dem Hinweis auf equals auch erklärbar, vielen Dank.

Zusammenfassung:
Beim Schreiben des HashCodes war HashCode Eindeutig (x,y,z aufgrund der Anforderungen aussreichend klein), entsprechend konnte aus equals so implementiert werden.
Durch neue Anforderung waren größere x,y,z möglich, die identische HashCodes für verschiedene Objekte und damit auch equals()=true produzieren konnten.

Die API habe ich insofern falsch (bzw nicht genau genug) gelesen, dass bei identischem Schlüssel nur der neue Wert, nicht aber der neue Schlüssel (ist ja auch sinnlos wenn er tatsächlich gleich gewesen wäre) durch den put()-Befehl in die HashMap geschrieben werden.

Nochmal vielen Dank,

Mathias
 
Beim Schreiben des HashCodes war HashCode Eindeutig (x,y,z aufgrund der Anforderungen aussreichend klein), entsprechend konnte aus equals so implementiert werden.
Grundsätzlich können verschiedene Objekte auch identische Hashcodes haben. Ich hoffe, du hast deine equals-Methode auch verbessert. Der Tipp von Landei mit der IDE ist gut.
 
Möglicherweise sind "hashCode()" und "equals()" ja hier gar nicht so interessant, weil verschiedene Transporter (Instanzen) Ladeflächen mit identischen Ausmaßen haben können. Allerdings wäre dann eine IdentityHashMap angebracht.
 

Zurück
Oben