Dies ist eine sehr klassische Frage in Java und wird während der Interviews häufig gestellt. Tatsächlich haben viele Bücher oder Artikel erwähnt, dass Sie die Methoden von HashCode () und Equals () überlasten müssen, um die Suche nach benutzerdefinierten Schlüssel in HashMap zu realisieren. Es scheint jedoch, dass nur wenige Artikel darüber sprechen, warum Sie dies tun müssen und welche Konsequenzen dies nicht tun werden. Daher werde ich diesen Artikel schreiben, um ihn zu erklären.
Was passiert zunächst, wenn wir die folgende Personenklasse direkt als Schlüssel verwenden und in HashMap speichern?
public class Person {private String -ID; öffentliche Person (String -ID) {this.id = id; }} importieren java.util.hashMap; public class main {public static void main (String [] args) {HashMap <Person, String> map = new Hashmap <Person, String> (); map.put (neue Person ("001"), "findingSea"); map.put (neue Person ("002"), "Linyin"); map.put (neue Person ("003"), "Henrylin"); map.put (neue Person ("003"), "findingSeeaily"); System.out.println (map.toString ()); System.out.println (map.get (neue Person ("001")); System.out.println (map.get (neue Person ("002")); System.out.println (map.get (neue Person ("003")); }}Was ist das Ausgangsergebnis?
{Person@6e4d4d5e = Henrylin, Person@275Cea3 = fandingSea, Person@15128ee5 = findingSeacey, Person@4513098 = Linyin} nullnullnullWir können sehen, dass es hier zwei Probleme gibt:
1. Während des Additionsprozesses haben wir zweimal das Schlüsselwertpaar von Key = New Person ("003") hinzugefügt. In der Erwartung sollte es in HashMap nur ein solches Schlüsselwertpaar geben. Da der Schlüssel (erwartet) der gleiche ist, sollte er nicht wiederholt hinzugefügt werden. Der value = "fandingSeaily" Das zweite Mal sollte den ursprünglichen Wert = "Henrylin" ersetzen. In der Eingabe stellten wir jedoch fest, dass die erwartete Situation nicht auftrat, aber es gibt zwei Schlüsselwertpaare von Wert = "fandingsesely" und value = "Henrylin" in HashMap, und ihre Schlüsselwerte sind immer noch unterschiedlich, was offensichtlich falsch ist.
2. Wenn wir den Wertwert erhalten, verwenden wir drei Personenobjekte, um zu suchen. Diese drei Objekte entsprechen den drei wichtigen Werten, die wir gerade gespeichert haben (in Erwartung), aber die Suche sind drei Nullwerte, was offensichtlich auch falsch ist.
Die richtige Methode wurde also an vielen Stellen tatsächlich beschrieben. Die Personklasse ist direkt modifiziert, überlastet Equals- und Hashcode -Methoden, und die modifizierte Personklasse lautet wie folgt:
public class Person {private String -ID; öffentliche Person (String -ID) {this.id = id; } @Override public boolean Equals (Objekt o) {if (this == o) return true; if (o == null || getClass ()! = o.getClass ()) return false; Person Person = (Person) o; if (id! = null?! id.equals (person.id): person.id! = null) return false; zurückkehren; } @Override public int HashCode () {return id! = Null? id.hashcode (): 0; }}Wenn wir dann das obige Inspektionsverfahren erneut ausführen, sind die Ergebnisse wie folgt:
{Person@ba31 = findingSea, Person@ba32 = linyin, Person@ba33 = fandingsesely} fandingSealinyInfindingsseeselyWie zu sehen ist, wurden alle hervorgehobenen Highlights und Fehler korrigiert. Warum passiert das?
In HashMap lautet die Reihenfolge des Vergleichs von Suchschlüssel:
1. Berechnen Sie den Hash -Code des Objekts, um festzustellen, ob es in der Tabelle vorhanden ist.
2. Überprüfen Sie, ob das Objekt im entsprechenden Hash -Code -Standort dem aktuellen Objekt entspricht.
Offensichtlich besteht der erste Schritt darin, die HashCode () -Methode () zu verwenden, und der zweite Schritt besteht darin, die Equals () -Methode zu verwenden. Wenn keine Überladung durchgeführt wird, werden diese beiden Methoden der Objektklasse in diesen beiden Schritten standardmäßig aufgerufen. Im Objekt wird die Berechnungsmethode des Hash -Codes basierend auf der Objektadresse berechnet. Die Objektadressen der beiden Person ("003") sind unterschiedlich, daher ist auch ihr Hash -Code unterschiedlich. Natürlich wird HashMap sie nicht als den gleichen Schlüssel behandeln. Gleichzeitig wird im Standard -Equals () des Objekts auch basierend auf der Adresse des Objekts verglichen. Natürlich sind eine Person ("003") und eine andere Person ("003") nicht gleich.
Nach dem Verständnis ist es leicht herauszufinden, warum Sie sowohl HashCode () als auch gleiche Methoden überladen müssen.
• Überlastung von HashCode () soll denselben Hash -Code für denselben Schlüssel erhalten, damit der HashMap auf dem von uns angegebenen Schlüssel positioniert werden kann.
• Überlastung Equals () muss HashMap zeigen, dass das aktuelle Objekt und das auf dem Schlüssel gespeicherte Objekt gleich sind, damit wir das dem Schlüssel entsprechende Schlüsselwertepaar wirklich erhalten können.
Es gibt ein weiteres Detail. In der Personklasse liegt die Betonung der HashCode () -Methode::
@Overridepublic int HashCode () {return id! = Null? id.hashcode (): 0;}Der Punkt, der hier verwirrt sein kann, ist: Warum kann der Hash -Code einer Variablen der Typ -Zeichenfolge als Hash -Code -Wert der Personklasse verwendet werden? Sind die Hash -Codes der neuen Person (neuer String ("003") und der neuen Person (neuer String ("003") gleich?
Schauen wir uns die Ausgabe des folgenden Code an:
System.out.println ("findingSea" .hashcode ()); String ("findingSea"). HashCode ()); 728795174728795174728795174728795174Sie können sehen, dass die Ausgänge der vier Aussagen alle gleich sind. Es ist sehr intuitiv und vernünftig zu erraten, dass der String -Typ auch HashCode () überlastet, um den Hash -Code -Wert gemäß dem Inhalt der Zeichenfolge zurückzugeben, sodass Zeichenfolgen mit demselben Inhalt den gleichen Hash -Code haben.
Gleichzeitig zeigt dies auch eine Frage: Warum müssen wir gleich () zum Vergleich verwenden, wenn wir wissen, dass HashCode () gleich ist? Dies liegt daran, dass es die Situation im obigen Beispiel vermeidet, da nach der Überlastung der HashCode () -Methode der Personenklasse die Personklasse direkt den Hash -Code -Wert der Member -ID des String -Typs als Hash -Code -Wert verwendet. Es ist jedoch offensichtlich, dass eine Person ("003") und eine String ("003") nicht gleich sind. Wenn HashCode () gleich ist, ist auch gleich () zu vergleichen.
Die folgenden Beispiele können als Beweis für die obige Beschreibung verwendet werden:
System.out.println (neue Person ("003"). HashCode ()); // 47667System.out.println (neuer String ("003"). HashCode ()); // 47667System.out.println (neue Person ("003"). Equals (New String ("003")); // FALSCHDer obige Artikel Java verwendet maßgeschneiderte Klassen als Schlüsselwertbeispiel von HashMap. Dies ist der gesamte Inhalt, den ich mit Ihnen teile. Ich hoffe, es kann Ihnen eine Referenz geben und ich hoffe, Sie können Wulin.com mehr unterstützen.