Wenn Sie Ihr eigenes Schlüsselpaarobjekt erstellen, sollten Sie sich einigen Dingen stellen.
Zunächst sollten Sie sich der Implementierung von hashCode()
und bewusst sein equals()
. Sie müssen dies tun.
Zweitens hashCode()
stellen Sie bei der Implementierung sicher, dass Sie verstehen, wie es funktioniert. Das angegebene Benutzerbeispiel
public int hashCode() {
return this.x ^ this.y;
}
ist tatsächlich eine der schlechtesten Implementierungen, die Sie tun können. Der Grund ist einfach: Sie haben viele gleiche Hashes! Und die hashCode()
sollten int-Werte zurückgeben, die eher selten und im besten Fall einzigartig sind. Verwenden Sie so etwas:
public int hashCode() {
return (X << 16) + Y;
}
Dies ist schnell und gibt eindeutige Hashes für Schlüssel zwischen -2 ^ 16 und 2 ^ 16-1 (-65536 bis 65535) zurück. Das passt in fast jedem Fall. Sehr selten sind Sie außerhalb dieser Grenzen.
Drittens sollten Sie bei der Implementierung equals()
auch wissen, wofür es verwendet wird, und wissen, wie Sie Ihre Schlüssel erstellen, da es sich um Objekte handelt. Oft tun Sie dies unnötig, wenn Anweisungen dazu führen, dass Sie immer das gleiche Ergebnis erzielen.
Wenn Sie Schlüssel wie diesen erstellen: map.put(new Key(x,y),V);
Sie werden niemals die Referenzen Ihrer Schlüssel vergleichen. Denn jedes Mal, wenn Sie auf die Karte zugreifen möchten, werden Sie so etwas tun map.get(new Key(x,y));
. Daher equals()
braucht man keine Aussage wieif (this == obj)
. Es wird niemals auftreten.
Anstatt if (getClass() != obj.getClass())
in Ihrer equals()
besseren Nutzung if (!(obj instanceof this))
. Es gilt auch für Unterklassen.
Das einzige, was Sie vergleichen müssen, ist tatsächlich X und Y. Also das Beste equals()
Implementierung in diesem Fall wäre also:
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
Am Ende sieht Ihre Schlüsselklasse also so aus:
public class Key {
public final int X;
public final int Y;
public Key(final int X, final int Y) {
this.X = X;
this.Y = Y;
}
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
public int hashCode() {
return (X << 16) + Y;
}
}
Sie können Ihre Dimensionsindizes X
und Y
eine öffentliche Zugriffsebene angeben, da diese endgültig sind und keine vertraulichen Informationen enthalten. Ich bin mir nicht 100% sicher, ob die private
Zugriffsebene in irgendeiner korrekt funktioniert beim Casting Object
auf a FallKey
.
Wenn Sie sich über das Finale wundern, erkläre ich alles als endgültig, welcher Wert auf Instanzen gesetzt ist und sich nie ändert - und daher eine Objektkonstante ist.