Vorwort
Wie wir alle wissen, hat Java.lang.Object eine HashCode () und eine Equals () -Methode, die eine wichtige Rolle im Softwaredesign spielen. Schreiben Sie diese beiden Methoden in einigen Klassen um, um einige wichtige Funktionen zu erfüllen.
1. Warum HashCode () verwenden?
Die Elemente im Set sind ungeordnet und nicht wiederholbar. Was ist die Grundlage für die Beurteilung, ob zwei Elemente wiederholt werden?
Einige Leute sagen: Object.equal() wird natürlich verwendet, um zu vergleichen, ob Objekte gleich sind. Es gibt jedoch eine große Anzahl von Objekten im Satz, und die Anzahl der Vergleiche von Objektelementen, die dem Satz hinzugefügt wurden, erhöht sich allmählich und verringert die Effizienz des Programmbetriebs erheblich. Java verwendet Hashing -Algorithmus (auch Hashing -Algorithmus genannt), um dieses Problem zu lösen. Das Objekt (oder Daten) wird direkt einer Adresse gemäß einem bestimmten Algorithmus zugeordnet, und die Zugriffseffizienz des Objekts wird erheblich verbessert.
Wenn ein Satz, der eine große Anzahl von Elementen enthält, ein Element (Objekt) hinzufügen muss, rufen Sie zuerst den HashCode () dieses Elements auf und Sie können den tatsächlichen Speicherort dieses Elements gleichzeitig positionieren. Wenn es an dieser Position kein Element gibt, bedeutet dies, dass dieses Objekt zum ersten Mal in der Sammlung gespeichert ist und das Objekt direkt an dieser Position gespeichert ist. Wenn an dieser Position ein Objekt vorhanden ist, rufen Sie Equal () auf, um festzustellen, ob die beiden Objekte gleich sind. Wenn das Gleiche wahr ist, verwerfen Sie das Element und existieren nicht. Wenn es nicht gleich ist, Hash für andere Adressen.
Dies ist auch der Grund, warum, wenn der Satz Set Objekttypdaten speichert, nicht nur die HashCode () -Methode des Objekts neu schreiben, sondern auch die Equals () -Methode neu schreiben.
2. Wie benutze HashCode ()?
Die Beziehung zwischen dem Rückgabewert von HashCode () und Equals ()
Hier ist ein Beispiel. In der tatsächlichen Softwareentwicklung ist es am besten, diese beiden Methoden neu zu schreiben.
public class Angestellte {int Mitarbeiter; Zeichenfolge Name; @Override public boolean gleich (Objekt obj) {if (obj == this) return true; Mitarbeiter emp = (Mitarbeiter) obj; if (EmployeeId.equals (emp.getOleMeId ()) && name == emp.getName ()) return true; false zurückgeben; } @Override public int HashCode () {int Hash = 1; Hash = Hash * 17 + Mitarbeiter; Hash = Hash * 31 + name.hashCode (); Return Hash; }}Die Methoden Equals () und HashCode () werden verwendet, um in derselben Klasse zu vergleichen, insbesondere wenn das gleiche Klassenobjekt im Container gespeichert ist, wie z. B. für Speichern von Objekten in derselben Klasse festgelegt.
Hier müssen wir zuerst ein Problem verstehen:
Zwei Objekte mit Equals () Equals, HashCode () müssen gleich sein, und zwei Objekte mit Equals () können nicht nachweisen, dass ihr HashCode () nicht gleich ist. Mit anderen Worten, für zwei Objekte, deren Equals () -Methode nicht gleich ist, kann HashCode () gleich sein.
Hier ist HashCode wie der Index jedes Zeichens im Wörterbuch und gleich () ist wie beim Vergleich verschiedener Wörter unter demselben Charakter im Wörterbuch. Genau wie im Wörterbuch sucht die Suche nach den beiden Wörtern "Selbst" und "spontan" unter dem Wort "Selbst" im Wörterbuch, wenn Equals () verwendet wird, um die Gleichheit der Wörter Abfrage zu bestimmen, ist es dasselbe Wort. Beispielsweise sind die beiden von Equals () verglichenen Wörter "Selbst", dann müssen die von der HashCode () -Methode erhaltenen Werte zu diesem Zeitpunkt gleich sein; Wenn Equals () -Methode die Wörter "Selbst" und "spontan" vergleicht, dann ist das Ergebnis, dass Sie nicht warten wollen, aber beide Wörter gehören zu den Wörtern "Selbst" und so ist bei der Suche nach Indizes, dh HashCode () das gleiche. Wenn Equals () die Wörter "Selbst" und "sie" vergleicht, sind auch die Ergebnisse unterschiedlich und die von HashCode () erzielten Ergebnisse sind zu diesem Zeitpunkt ebenfalls unterschiedlich.
Umgekehrt: HashCode () ist unterschiedlich und Equals () kann eingeführt werden; HashCode () ist gleich, gleich () kann gleich sein oder nicht gleich.
In der Objektklasse ist die HashCode () -Methode eine lokale Methode, die den Adresswert des Objekts zurückgibt. Die Equals () -Methode in der Objektklasse vergleicht auch die Adresswerte der beiden Objekte. Wenn Equals () gleich ist, bedeutet dies, dass die Adresswerte der beiden Objekte ebenfalls gleich sind. Natürlich ist Hashcode () gleich.
Warum ist Equals genauer, um gleiche Elemente zu vergleichen, warum die HashCode () -Methode verwenden?
Weil der Hash -Algorithmus bei der Suche nach Elementen eine hohe Effizienz bietet, wenn Sie herausfinden möchten, ob eine Sammlung ein Objekt enthält, wie Sie den ungefähren Programmcode schreiben?
Normalerweise nehmen Sie jedes Element eins nach dem anderen heraus, um sie mit dem von Ihnen gesuchten Objekt zu vergleichen. Wenn Sie feststellen, dass das Ergebnis des Equals -Methodenvergleichs zwischen einem Element und dem von Ihnen gesuchten Objekt aufhören und positive Informationen zurückgeben. Andernfalls geben Sie negative Informationen zurück. Wenn es in einer Sammlung viele Elemente gibt, z. B. 10.000 Elemente und nicht das von Ihnen gesuchte Objekt enthalten, bedeutet dies, dass Ihr Programm 10.000 Elemente aus der Sammlung herausnehmen und eins nach dem anderen vergleichen muss, um eine Schlussfolgerung zu erhalten.
Die Objektklasse definiert eine HashCode () -Methode, um den Hash -Code jedes Java -Objekts zurückzugeben. Bei der Suche nach einem Objekt aus der Hashset -Sammlung ruft das Java -System zunächst die Methode HashCode () des Objekts auf, um die Hash -Code -Tabelle des Objekts zu erhalten, und findet dann den entsprechenden Speicherbereich basierend auf dem Hash und schließlich jedes Element im Speicherbereich und vergleicht es mit dem Objekt für die Equals -Methode. Auf diese Weise können Sie die Schlussfolgerung ziehen, ohne alle Elemente in der Sammlung zu durchqueren. Es ist ersichtlich, dass die Hashset -Sammlung eine gute Leistung des Objektabrufs hat.
Die Effizienz des Speicherns von Objekten in der Hashset -Sammlung ist jedoch relativ niedrig, da beim Hinzufügen eines Objekts zur Hashset -Sammlung der Hash -Code des Objekts zuerst berechnet werden muss und der Speicherort des Objekts in der Sammlung basierend auf diesem Hash -Code bestimmt wird. Um sicherzustellen, dass die Instanzobjekte einer Klasse normalerweise in Hashset gespeichert werden können, müssen die Ergebnisse der beiden Instanzobjekte dieser Klasse im Vergleich zur Equals () -Methode gleich sein. Das heißt, wenn das Ergebnis von obj1.equals(obj2) wahr ist, muss das Ergebnis des folgenden Ausdrucks auch true:obj1.hashCode() == obj2.hashCode() .
Mit anderen Worten: Wenn wir die Equals -Methode eines Objekts neu schreiben, müssen wir seine Hashcode -Methode neu schreiben. Wenn wir seine HashCode -Methode nicht neu schreiben, gibt die HashCode -Methode im Objektobjekt immer die Hash -Adresse eines Objekts zurück, und diese Adresse ist niemals gleich. Selbst wenn die Equals -Methode zu diesem Zeitpunkt neu geschrieben wird, wird es keinen spezifischen Effekt geben, denn wenn die HashCode -Methode nicht warten möchte, wird die Equals -Vergleichsmethode nicht aufgerufen, sodass sie bedeutungslos ist.
Die meisten Datenstrukturen verwenden die Equals -Methode, um festzustellen, ob sie ein Element enthalten, z. B.:
Liste <String> list = arrays.aslist ("a", "b", "c"); boolean enthält = list.contains ("b"); Diese Variable enthält das Ergebnis ist wahr, da "b" unterschiedliche Instanzen sind (zusätzlich wird die String -Residenz ignoriert), sie sind jedoch gleich.
Sie verwenden einen schnellen Weg, um die Gleichstellung der potenziellen Instanz zu vergleichen, anstatt jedes in der Instanz enthaltene Element zu vergleichen. Der schnelle Vergleich erfordert nur den Vergleich der folgenden Aspekte:
Vergleich von Abkürzungen bedeutet, dass durch den Vergleich von Hash -Werten eine Instanz durch einen Ganzzahlwert ersetzen kann. Instanzen mit demselben Hash -Code sind nicht unbedingt gleich, aber Instanzen mit Gleichheit müssen den gleichen Hash -Wert haben. (oder sollte dies bald diskutieren) Diese Datenstrukturen werden häufig von dieser Technik bezeichnet, und sie können durch Hash identifiziert werden, darunter HashMap ist der berühmteste Vertreter.
Sie arbeiten normalerweise so:
Wenn ein Element hinzugefügt wird, wird sein Hash-Code verwendet, um den Index des internen Arrays (dh der sogenannte Eimer) zu berechnen).
Wenn ja, ungleiche Elemente haben den gleichen Hash -Code, landen sie auf demselben Eimer und bündeln zusammen, indem sie die Liste hinzufügen.
Wenn eine Instanz ausgeführt wird, enthält Operationen, sein Hash -Code wird verwendet, um den Bucket -Wert (Indexwert) zu berechnen, und die Instanz wird nur verglichen, wenn Elemente auf dem entsprechenden Indexwert vorhanden sind.
Daher ist HashCode in der Objektklasse definiert.
Wenn HashCode als Verknüpfung zur Bestimmung der Gleichstellung verwendet wird, gibt es nur eine Sache, die uns kümmern sollte: Gleiche Objekte sollten denselben HashCode haben. Wenn wir die Equals -Methode überschreiben, müssen wir eine HashCode -Implementierung erstellen, die dem sie entspricht!
Andernfalls haben gleiche Objekte möglicherweise nicht den gleichen Hash -Code, da sie die Standardimplementierung von Objekten aufrufen.
Zitat aus offiziellen Dokumenten
Hashcode General Convention:
Wenn Sie dasselbe Objekt aufrufen, das in einer Java -Anwendung ausgeführt wird, muss die HashCode -Methode immer dieselbe Ganzzahl zurückgeben. Diese Ganzzahl muss nicht über verschiedene Java -Anwendungen konsistent sein. Gemäß equals(Object) -Methode muss die beiden Objekte die HashCode -Methode aufrufen, wenn zwei Objekte gleich sind, das gleiche Ergebnis erzielen.
Gemäß equals(Object) -Methode erzeugt das Aufrufen der HashCode -Methode, wenn die beiden Objekte nicht gleich sind, nicht unbedingt unterschiedliche Ganzzahlergebnisse. Programmierer sollten jedoch erkennen, dass die Erzeugung verschiedener Ganzzahlergebnisse für ungleiche Objekte wahrscheinlich die Leistung der Hash -Tabelle verbessern wird.
HashCode -Implementierung
Hier ist eine einfache Implementierung von person.hashcode() :
@Overridepublic int HashCode () {return object.hash (FirstName, LastName);}Die Person berechnet den Hash -Code durch Kombination mehrerer Felder. Alle werden durch die Hash -Funktion des Objekts berechnet.
Wählen Sie ein Feld aus
Aber welche Felder sind verwandt? Die Anforderungen helfen uns, diese Frage zu beantworten:
Wenn ein gleiches Objekt denselben Hash -Code haben muss, sollte der berechnete Hash -Code keine Felder enthalten, die nicht für Gleichheitsüberprüfungen verwendet werden. (Ansonsten sind die beiden Objekte nur so, dass diese Felder unterschiedlich sind, aber sie sind möglicherweise immer noch gleich, aber die Hash -Codes der beiden Objekte sind zu diesem Zeitpunkt unterschiedlich.) Die Untergruppe der Felder, die verwendet werden, wenn die Hash -Gruppenfelder gleich sind. Die gleichen Felder werden standardmäßig verwendet, es sind jedoch einige Details zu berücksichtigen.
Zusammenfassen
Wir verstehen, dass die Berechnung des Hash -Codes darin besteht, einen gleichen Ganzzahlwert zu komprimieren: Gleiche Objekte müssen denselben Hash -Code haben, und für Leistungsüberlegungen ist es am besten, denselben Hash -Code so wenig wie möglich zu teilen.
Dies bedeutet, dass die HashCode -Methode neu geschrieben werden muss, wenn die Equals -Methode neu geschrieben wird.
Wenn die Implementierung von HashCode die gleichen Felder verwendet, wie in gleichem (oder einer Teilmenge von Feldern, die in gleichem) verwendet werden)
Es ist am besten, nicht veränderliche Felder aufzunehmen. Betrachten Sie nicht, HashCode für Sammlungen aufzurufen. Wenn es keinen speziellen Eingangsmodus gibt, versuchen Sie, einen allgemeinen Hash -Algorithmus zu verwenden.
Okay, das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.