Über Hashcode, in Wikipedia:
In der Java-Programmiersprache liefert jede Klasse implizit oder explizit eine HashCode () -Methode, die die in einer Instanz der Klasse gespeicherten Daten in einen einzelnen Hash-Wert (eine 32-Bit-Signierinsteger) verdauert.
Hashcode extrahiert eine 32-Bit-Ganzzahl basierend auf allen in einer Objektinstanz gespeicherten Daten. Der Zweck dieser Ganzzahl ist es, die Einzigartigkeit der Instanz anzuzeigen. Es ist dem MD5 -Code etwas ähnlich, und jede Datei kann einen eindeutigen MD5 -Code über den MD5 -Algorithmus generieren. Der HashCode in Java implementiert jedoch den HashCode nicht wirklich, um einen eindeutigen Hashcode für jedes Objekt zu generieren, und es besteht immer noch eine gewisse Chance auf Duplizierung.
Schauen wir uns zuerst die Objektkurs an. Wir wissen, dass die Objektklasse die direkte oder indirekte übergeordnete Klasse aller Klassen in einem Java -Programm ist und am höchsten Punkt der Klassenebene ist. Viele gängige Methoden sind in der Objektklasse definiert, einschließlich der Hashcode -Methode, über die wir sprechen möchten, wie folgt
Public Final Native Class <?> getClass (); public native int hashcode (); public boolean gleich (Objekt obj) {return (this == obj); } public String toString () {return getClass (). getName () + "@" + Integer.tohexString (HashCode ()); }Beachten Sie, dass vor der HashCode-Methode einen nativen Modifikator vorhanden ist, was bedeutet, dass die HashCode-Methode in einer Nicht-Java-Sprache implementiert wird. Die spezifische Methode wird extern implementiert und gibt die Adresse des Speicherobjekts zurück.
In vielen Java -Klassen werden Gleich- und Hashcode -Methoden umgeschrieben. Warum ist das? Die häufigste String -Klasse, wie wenn ich zwei Zeichenfolgen mit denselben Zeichen definiere, sollte das Ergebnis, das ich möchte, gleich. Wenn Sie die Methoden der Equals und HashCode nicht überschreiben, sind sie definitiv nicht gleich, da die Speicheradressen der beiden Objekte unterschiedlich sind.
public int hashcode () {int h = hash; if (h == 0) {int off = offset; char val [] = Wert; int len = count; für (int i = 0; i <len; i ++) {H = 31*H+val [off ++]; } Hash = H; } return h; }Tatsächlich ist dieser Code die Implementierung dieses mathematischen Ausdrucks
s [0]*31^(n-1) + s [1]*31^(n-2) +… + s [n-1]
S [i] ist das I-te Zeichen einer Schnur, und n ist die Länge einer String. Warum dann 31 hier anstelle anderer Zahlen verwenden? Effektiver Java sagt Folgendes: Der Grund, warum 31 ausgewählt wird, ist, dass es sich um eine seltsame Primzahl handelt. Wenn der Multiplikator eine gleichmäßige Zahl und die Multiplikationsüberläufe ist, gehen die Informationen verloren, da sich die Multiplikation mit 2 dem Verschiebungsbetrieb entspricht. Die Vorteile der Verwendung von Primzahlen sind nicht offensichtlich, aber die Hash -Ergebnisse werden konventionell zur Berechnung der Hash -Ergebnisse verwendet. 31 hat ein gutes Merkmal, das die Verwendung von Verschiebung und Subtraktion anstelle einer Multiplikation verwenden soll, um eine bessere Leistung zu erzielen: 31*i == (i << 5) -i. VMs können diese Optimierung automatisch vervollständigen.
Wie Sie sehen können, verwendet die String -Klasse ihren Wertwert als Parameter, um HashCode zu berechnen, dh der gleiche Wert hat definitiv den gleichen HashCode -Wert. Dies ist auch leicht zu verstehen, da die Wertwerte gleich sind. Wenn also auch der Equals -Vergleich gleich ist, ist die Equals -Methode gleich, dann muss der HashCode gleich sein. Der andere Weg ist nicht unbedingt wahr. Es garantiert nicht, dass der gleiche HashCode das gleiche Objekt haben muss.
Eine gute Hash -Funktion sollte so aussehen: Erzeugen Sie ungleiche Hashcodes für verschiedene Objekte.
In idealen Fällen sollte die Hash -Funktion gleichmäßig ungleiche Instanzen im SET auf alle möglichen Hashcodes verteilen. Es ist sehr schwierig, diese ideale Situation zu erreichen, zumindest hat Java sie nicht erreicht. Weil wir sehen können, dass Hashcode nicht zufällig erzeugt wird und bestimmte Regeln enthält, was die obige mathematische Gleichung ist. Wir können einige konstruieren, die den gleichen HashCode haben, aber unterschiedliche Wertwerte, zum Beispiel: Der Hashcode von AA und BB ist gleich.
Der folgende Code:
public class main {public static void main (String [] args) {main m = new main (); System.out.println (M); System.out.println (Integer.tohexString (m.hashcode ())); Zeichenfolge a = "aa"; Zeichenfolge b = "BB"; System.out.println (a.hashcode ()); System.out.println (b.hashcode ()); }}Ausgangsergebnis:
Haupt@2A139A55 2A139A55 2112 2112
Im Allgemeinen müssen Sie beim Umschreiben der gleichen Funktion auch die HashCode -Funktion neu schreiben. Warum ist das?
Schauen wir uns dieses Beispiel an. Lassen Sie uns einen einfachen Klassenangestellten erstellen
public class Angestellte {private Integer id; private String FirstName; private Zeichenfolge Lastname; private Stringabteilung; public Integer getid () {return id; } public void setId (Integer id) {this.id = id; } public String getFirstName () {return firstname; } public void setFirstName (String FirstName) {this.firstname = firstName; } public String getLastName () {return LastName; } public void setLastName (String LastName) {this.lastName = lastName; } public String getDepartment () {Rückgabeabteilung; } public void setDepartment (String -Abteilung) {this.Department = Abteilung; }}Die obige Arbeitnehmerklasse hat nur einige sehr grundlegende Eigenschaften, Getter und Setter. Betrachten Sie nun eine Situation, in der Sie zwei Mitarbeiter vergleichen müssen.
public class Equalstest {public static void main (String [] args) {Mitarbeiter e1 = neuer Mitarbeiter (); Mitarbeiter e2 = neuer Mitarbeiter (); e1.setid (100); e2.setid (100); // druckt false in Console System.out.println (e1.equals (e2)); }}Es besteht kein Zweifel, dass das obige Programm falsch ausgibt, aber tatsächlich die beiden oben genannten Objekte durch einen Mitarbeiter darstellen. Die eigentliche Geschäftslogik hofft, dass wir wahr zurückkehren.
Um dies zu erreichen, müssen wir die Equals -Methode neu schreiben.
public boolean gleich (Objekt o) {if (o == null) {return false; } if (o == this) {return true; } if (getClass ()! = o.getClass ()) {return false; } Mitarbeiter e = (Mitarbeiter) o; return (this.getId () == e.getId ());}; Fügen Sie diese Methode in die obige Klasse hinzu und Eauqlstest wird true ausgegeben.
Also sind wir fertig? Nein, ändern wir die Testmethode und schauen uns an.
Import Java.util.hashset; Import Java.util.set; öffentliche Klasse Equalstest {public static void main (String [] args) {Mitarbeiter e1 = neuer Mitarbeiter (); Mitarbeiter e2 = neuer Mitarbeiter (); e1.setid (100); = neuer Hashset <Personal> (); Mitarbeiter.Add (E1); Mitarbeiter.Add (E2); // druckt zwei ObjekteSystem.out.println (Mitarbeiter);}Das obige Programm gibt zwei Ergebnisse aus. Wenn die beiden Mitarbeiterobjekte der Rückgabe true, sollte nur ein Objekt im Satz gespeichert werden. Was ist das Problem?
Wir haben die zweite wichtige Methode Hashcode () vergessen. So wie Javadoc von JDK sagte, müssen Sie die Methode von HashCode () neu schreiben, wenn Sie die Methode Equals () neu schreiben. Fügen wir die folgende Methode hinzu und das Programm wird korrekt ausgeführt.
@Override public int HashCode () {final int prime = 31; int result = 1; Ergebnis = Prime * Ergebnis + getId (); Rückgabeergebnis; }Dinge, an die man sich erinnern sollte
Versuchen Sie sicherzustellen, dass die gleiche Eigenschaft des Objekts verwendet wird, um zwei Methoden zu generieren: HashCode () und Equals (). In unserem Fall verwenden wir Mitarbeiter -IDs.
Die EQAULS -Methode muss konsistent sein (wenn das Objekt nicht geändert wird, sollte Equals denselben Wert zurückgeben).
So lange wie A.equals (b) muss A.Hashcode () gleich b.hashcode () sein.
Beide müssen gleichzeitig umgeschrieben werden.
Zusammenfassen
Das Obige dreht sich alles um das ausführliche Verständnis dieses Artikels für die Hashcode-Methode in Java, und ich hoffe, dass es für alle hilfreich sein wird. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!