HashMap
enthält eine bestimmte Anzahl von Eimern. Hiermit wird hashCode
bestimmt, in welchen Eimer diese gelegt werden sollen. Stellen Sie sich der Einfachheit halber als Modul vor.
Wenn unser Hashcode 123456 lautet und wir 4 Eimer haben, wird 123456 % 4 = 0
der Artikel in den ersten Eimer, Eimer 1, verschoben.
Wenn unsere Hashcode-Funktion gut ist, sollte sie eine gleichmäßige Verteilung bieten, damit alle Buckets etwas gleich verwendet werden. In diesem Fall verwendet der Bucket eine verknüpfte Liste zum Speichern der Werte.
Sie können sich jedoch nicht darauf verlassen, dass Leute gute Hash-Funktionen implementieren. Menschen schreiben oft schlechte Hash-Funktionen, was zu einer ungleichmäßigen Verteilung führt. Es ist auch möglich, dass wir mit unseren Eingaben einfach Pech haben.
Je geringer diese Verteilung ist, desto weiter bewegen wir uns von O (1) -Operationen und desto näher kommen wir O (n) -Operationen.
Die Implementierung von Hashmap versucht dies zu mildern, indem einige Buckets in Bäumen anstatt in verknüpften Listen organisiert werden, wenn die Buckets zu groß werden. Dafür ist da TREEIFY_THRESHOLD = 8
. Wenn ein Eimer mehr als acht Elemente enthält, sollte er zu einem Baum werden.
Dieser Baum ist ein rot-schwarzer Baum. Es wird zuerst nach Hash-Code sortiert. Wenn die Hash-Codes identisch sind, wird die compareTo
Methode verwendet, Comparable
ob die Objekte diese Schnittstelle implementieren, andernfalls der Identitäts-Hash-Code.
Wenn Einträge aus der Karte entfernt werden, kann sich die Anzahl der Einträge im Bucket verringern, sodass diese Baumstruktur nicht mehr erforderlich ist. Dafür ist das da UNTREEIFY_THRESHOLD = 6
. Wenn die Anzahl der Elemente in einem Bucket unter sechs fällt, können Sie auch wieder eine verknüpfte Liste verwenden.
Endlich gibt es die MIN_TREEIFY_CAPACITY = 64
.
Wenn eine Hash-Map größer wird, ändert sie automatisch ihre Größe, um mehr Buckets zu haben. Wenn wir eine kleine Hash-Karte haben, ist die Wahrscheinlichkeit, dass wir sehr volle Eimer bekommen, ziemlich hoch, da wir nicht so viele verschiedene Eimer haben, in die wir Sachen stecken können. Es ist viel besser, eine größere Hash-Karte mit mehr Eimern zu haben, die weniger voll sind. Diese Konstante besagt im Grunde, dass wir nicht damit beginnen sollen, Eimer in Bäume zu verwandeln, wenn unsere Hash-Karte sehr klein ist. Stattdessen sollte die Größe geändert werden, damit sie zuerst größer wird.
Um Ihre Frage zum Leistungsgewinn zu beantworten, wurden diese Optimierungen hinzugefügt, um den schlimmsten Fall zu verbessern . Ich spekuliere nur, aber Sie würden aufgrund dieser Optimierungen wahrscheinlich nur dann eine spürbare Leistungsverbesserung feststellen, wenn Ihre hashCode
Funktion nicht sehr gut wäre.
String
haben einen weitaus größeren Wertebereich als derint
Hashcode, daher sind Kollisionen unvermeidbar. Jetzt hängt es von den tatsächlichen Werten ab, wie die tatsächlichenString
s, die Sie in die Karte einfügen, ob Sie eine gleichmäßige Verteilung erhalten oder nicht. Eine schlechte Verteilung kann das Ergebnis von Pech sein.