Vergleich verschiedener Möglichkeiten, um dieselben Elemente von Hashmap, Hashset, Treemap und Treeset in Java zu beurteilen
1.1 Hashmap
Schauen wir uns zunächst an, wie Elemente in HashMap gespeichert werden. Jedes in der Karte gespeicherte Element ist ein Schlüsselwertpaar wie den Schlüsselwert und wird durch die Put-Methode hinzugefügt. Darüber hinaus hat der gleiche Schlüssel nur einen Wert, der in der Karte zugeordnet ist. Die Put -Methode ist in der Karte wie folgt definiert.
V put (k key, v Wert);
Es wird verwendet, um ein Schlüsselwertpaar wie den Schlüsselwert zu speichern. Der Rückgabewert ist der alte Wert, der vom Schlüssel auf der Karte gespeichert ist. Wenn es vorher nicht existiert, wird NULL zurückgegeben. Auf diese Weise wird die HashMap -Put -Methode implementiert.
public v put (k key, v value) {if (key == null) return putFornullKey (Wert); int Hash = Hash (Schlüssel); int i = indexFor (Hash, Tabelle.length); für (Eintrag <k, v> e = table [i]; e! = null; e = e.next) {Objekt k; if (e.hash == Hash && ((k = E.Key) == Key || key.equals (k))) {v oldValue = e.Value; E. value = Wert; E. recordaccess (this); kehren Sie OldValue zurück; }} modcount ++; AddEntry (Hash, Schlüssel, Wert, i); null zurückkehren; }Aus dem obigen Punkt können wir sehen, dass beim Hinzufügen der entsprechenden Schlüsselwertkombination der entsprechende Wert direkt geändert und der alte Wert zurückgegeben wird, wenn der entsprechende Schlüssel vorhanden ist. Bei der Beurteilung, ob der Schlüssel existiert, wird der Hashcode des Schlüssels zuerst verglichen, und dann wird der Hashcode des Schlüssels mit gleichem oder gleichem Vergleich. Wir können es hier vielleicht nicht sehen. Aus dem obigen Code vergleichen wir den HashCode von MAP.Entry und den HashCode des Schlüssels. Tatsächlich können wir sehen, dass MAP.Entry Hashcode tatsächlich der Hashcode ihres Schlüssels ist. Wenn der entsprechende Schlüssel ursprünglich nicht vorhanden ist, wird AddEntry aufgerufen, um den entsprechenden Schlüsselwert zur Karte hinzuzufügen. Der von AddEnndy übergebene Parameter -Hash ist der HashCode, der dem Schlüssel entspricht. Schauen wir uns als nächstes die Methodendefinition von AddEntry an.
void addentry (int hash, k key, v -Wert, int bucketIndex) {if ((size> = threshold) && (null! Hash = (null! = Schlüssel)? Hash (Schlüssel): 0; bucketIndex = indexFor (Hash, Tabelle.length); } createEntry (Hash, Schlüssel, Wert, BucketIndex); } void createEntry (int Hash, K -Schlüssel, V -Wert, int bucketIndex) {Eintrag <k, v> e = table [bucketIndex]; Tabelle [bucketIndex] = neuer Eintrag <> (Hash, Schlüssel, Wert, e); Größe ++; }Der Kern von AddEntry besteht darin, CreateStry aufzurufen, um eine Karte zu erstellen. Das Einsetzen des entsprechenden Schlüsselwerts repräsentiert und speichern. Offensichtlich ist die obige Tabelle eine Auswahl von Karte. Map.Entry verwendet einen Eigenschafts -Hash, um den HashCode des entsprechenden Schlüssels zu speichern. Schauen wir uns den Konstruktor von MAP an.
Eintrag (int H, k k, v v, Eintrag <k, v> n) {value = v; Weiter = n; Key = k; Hash = H; }Offensichtlich speichert es den HashCode, der dem entsprechenden Schlüssel, Wert und Schlüssel entspricht.
Nach dem Verständnis, wie Hashmap Elemente speichert, ist es einfacher zu sehen, wie Hashmap Elemente speichert. In HashMap gibt es zwei Hauptmethoden, um festzustellen, ob die Elemente gleich sind. Einer besteht Tatsächlich haben wir bei der Einführung der Einführung von HashMap -Elementen eingeführt, wie HashMap bestimmt, ob der Elementschlüssel gleich ist. Das heißt, der HashCode ist zunächst der gleiche, und zweitens sind die Schlüssel gleich oder gleich. Die Bestimmung, ob der Schlüssel in der Karte gleich ist, erfolgt über die Methode containkey (), und seine Implementierung in HashMap lautet wie folgt.
public boolean enthälty (Objektschlüssel) {return GetEntry (Schlüssel)! = NULL; } Endeintrag <k, v> GetEntry (Objektschlüssel) {int Hash = (Key == NULL)? 0: Hash (Schlüssel); für (Eintrag <k, v> e = table [indexFor (Hash, Tabelle.Length)]; e! = null; e = E.Next) {Objekt k; if (e.hash == Hash && ((k = E.Key) == Key || (Schlüssel! = NULL && key.equals (k)))) return e; } return null; }Es ist offensichtlich, dass es zuerst bestimmt, ob der HashCode des Schlüssels gleich ist, und dann feststellt, ob der Schlüssel gleich oder gleich ist.
Der in MAP verwendete Wert wird nach der entsprechenden Wertmodmethode beurteilt, und seine Implementierung in HashMap lautet wie folgt.
public boolean enthält value (Objektwert) {if (value == null) return enthält nullValue (); Eintrag [] tab = Tabelle; für (int i = 0; i <tab.length; i ++) für (Eintrag e = tab [i]; e! = null; e = e.Next) if (value.equals (e.Value)) return true; false zurückgeben; }Offensichtlich wird der Wert der Nicht-Null-Form anhand der Gleichen des Wertes beurteilt, und die Nullform ist so lange, wie sie gleich ist, dh der Wert im gespeicherten Element ist null.
1.2 Hashset
Nachdem er weiß, wie Hashmap Elemente speichert und feststellt, ob Elemente gleich sind, ist es einfacher zu erkennen, wie Hashset feststellt, ob Elemente gleich sind.
Die Elemente im Hashset werden tatsächlich durch HashMap gespeichert. Jedes Hashset -Objekt enthält einen Verweis auf das entsprechende HashMap -Objekt. Beim Hinzufügen und Löschen von Elementen zum Hashset wird es über die von ihm gehaltene Hashmap durchgeführt. Wenn Sie ein Element speichern, speichert es das entsprechende Element als Schlüssel des gehaltenen Hashmaps. Der entsprechende Wert ist ein konstantes Objekt. Wenn er ihn speichert, wird die Logik zur Bestimmung verwendet, ob die Elemente gleich sind. Bei der Feststellung, ob ein Element enthalten ist, ruft es auch die enthaltende Methode der HashMap auf, die zur Entscheidung von Urteilen gehalten wird.
public boolean enthält (Objekt o) {returnMap.ContainsKey (o); }Interessierte Freunde können den Quellcode von Hashset überprüfen.
1.3 Treemap
Die in Treemap gespeicherten Elemente werden nach dem Schlüssel bestellt und sortiert. Treemap hat zwei Möglichkeiten, gespeicherte Elemente zu sortieren. Einer besteht darin, den von ihm gehaltenen Komparator zu sortieren, und der andere soll den Schlüssel sortieren, der die vergleichbare Schnittstelle implementiert. Die erste Methode wird bevorzugt. Wenn der gehaltene Komparator (der Standard ist null) null ist, wird die zweite Methode verwendet. Treemap hat mehrere Konstruktoren, durch die der von ihm gehaltene Komparator initialisiert werden kann. Schauen wir uns zunächst an, wie Treemap Elemente spart. Die Put -Methode wird wie folgt implementiert.
public v put (k key, v Wert) {Eintrag <k, v> t = root; if (t == null) {compare (Schlüssel, Schlüssel); // type (und mögliche NULL) prüfen Root = neuer Eintrag <> (Schlüssel, Wert, NULL); Größe = 1; ModCount ++; null zurückkehren; } int cmp; Eintrag <k, v> Eltern; // Split -Komparator und vergleichbare Pfade vergleicher <? Super k> cpr = vergleicher; if (cpr! = null) {do {parent = t; CMP = CPR.comPare (Schlüssel, T.Key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; sonst return t.setValue (Wert); } while (t! = null); } else {if (key == null) geworfen nullpointerexception (); Vergleichbar <? Super k> k = (vergleichbar <? Super K>) Key; do {parent = t; cmp = k.comPareto (T.Key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; sonst return t.setValue (Wert); } while (t! = null); } Eintrag <k, v> e = neuer Eintrag <> (Schlüssel, Wert, Eltern); if (cmp <0) parent.left = e; sonst parent.right = e; FixAfterInsertion (e); Größe ++; ModCount ++; null zurückkehren; }Aus der obigen Implementierung können wir feststellen, dass das erste Element direkt gespeichert wird. Die folgenden Elemente sind in zwei Situationen unterteilt, einer ist der Fall, in dem der Vergleich nicht leer ist, und der andere ist der Fall, in dem der Vergleiche leer ist. Wenn der Komparator nicht leer ist, bestimmt der Komparator die Position des gespeicherten Elements. Eine wichtige Sache ist, dass beim Vergleich des Schlüssels des vorhandenen Elements mit dem Schlüssel des aktuell gespeicherten Elements 0 beträgt, dass der Schlüssel des aktuell gespeicherten Elements bereits in der ursprünglichen Karte vorhanden ist und der Wert, der dem ursprünglichen Schlüssel entspricht, in den neuen Wert geändert wird und der alte Wert direkt zurückgegeben wird. Wenn der gehaltene Komparator leer ist, wird die Position des Elements durch die Vergleichsmethode des Schlüssels bestimmt, die die vergleichbare Schnittstelle implementiert. Ein ähnliches Vergleicher ist, dass bei der Vergleich des ursprünglichen Schlüssels mit dem neu gespeicherten Schlüssel 0 beträgt, dass der neu gespeicherte Schlüssel bereits in der ursprünglichen Karte vorhanden ist und der Wert des entsprechenden Originalschlüssels direkt geändert wird und das Schlüsselwertpaar nicht länger gespeichert wird. Tatsächlich ist die wichtigste Implementierungslogik der Methode enthält, die feststellt, ob das Element existiert, ähnlich und die spezifische Implementierung wie folgt.
public boolean enthälty (Objektschlüssel) {return GetEntry (Schlüssel)! = NULL; } Finaleintrag <k, v> getEntry (Objektschlüssel) {// Vergleichs-basierte Version für Leistung, um die Leistung zu willen, wenn (vergleicher! if (key == null) geworfen nullpointerexception (); Vergleichbar <? Super k> k = (vergleichbar <? Super K>) Key; Eintrag <k, v> p = root; while (p! = null) {int cmp = k.comPareto (P.Key); if (cmp <0) p = P.Left; elseif (cmp> 0) p = P.Right; sonst return p; } return null; }Da die Logik von Treemap zur Bestimmung besteht, ob ein Element vorhanden ist, um zu bestimmen, ob das Ergebnis nach dem Vergleich des Vergleichs oder der Vergleichs 0 ist, sollten wir besonders vorsichtig sein, wenn wir TREEMAP zur Implementierung einer ähnlichen Logik wie Element Equals verwenden.
Die Logik der Treemap enthält den Wert, zu bestimmen, ob der entsprechende Wert gleich ist? Ähnlich wie HashMap. Interessierte Freunde können den Quellcode von Treemap überprüfen.
1.4 Treeset
Treeset ist auch eine Implementierung von SET. Die gespeicherten Elemente werden nicht wiederholt und bestellt. Standardmäßig müssen die gespeicherten Elemente die vergleichbare Schnittstelle implementieren, da die Elemente standardmäßig als vergleichbare Objekte verglichen werden. Treeset kann auch verwendet werden, um die darin gespeicherten Elemente durch den Komparator zu vergleichen. Dies kann erreicht werden, indem ein Vergleichsobjekt oder ein Treemap -Halten eines Vergleichsobjekts beim Bau eines Treesets geleitet werden. Die Implementierung von Treeset ähnelt der von Hashset. Es enthält auch einen Verweis auf eine Karte, bezieht sich jedoch nicht auf eine Hashmap, sondern auf Treemap. Die Hinzufügung und Löschung von Elementen in Treeset werden alle durch das Treemap implementiert, das sie halten. Ähnlich wie bei Hashset stimmt der Weg, um festzustellen, ob Elemente in Treeset gleich sind, mit Treemap überein und wird auch durch Vergleicher oder vergleichbar und nicht durch die herkömmliche Equals -Methode bestimmt. Interessierte Freunde können den Quellcode von Treeset überprüfen.
Danke fürs Lesen, ich hoffe, es kann Ihnen helfen. Vielen Dank für Ihre Unterstützung für diese Seite!