Ich habe kürzlich erfahren, dass in Java 8 Hash-Maps einen binären Baum anstelle einer verketteten Liste verwenden und Hash-Code als Verzweigungsfaktor verwendet wird. Ich verstehe, dass im Falle einer hohen Kollision die Suche auf O (log n) reduziert wird O meine Frage ist, was es wirklich tut, da die amortisierte Zeitkomplexität immer noch O (1) ist und vielleicht, wenn Sie die Speicherung aller Einträge im selben Bucket erzwingen, indem Sie den gleichen Hash-Code bereitstellen alle Schlüssel können wir einen signifikanten Zeitunterschied sehen, aber niemand in ihren richtigen Köpfen würde das tun.
Der Binärbaum verwendet auch mehr Platz als die einfach verknüpfte Liste, da er sowohl den linken als auch den rechten Knoten speichert. Warum die Komplexität des Platzes erhöhen, wenn die Zeitkomplexität außer einigen unechten Testfällen absolut nicht verbessert wird.
Dies ist hauptsächlich sicherheitsrelevante Änderung. In normalen Situationen ist es selten möglich, viele Kollisionen zu haben, wenn Hash-Schlüssel von nicht vertrauenswürdigen Quellen kommen (zB HTTP-Header-Namen vom Client), dann ist es möglich und nicht sehr schwierig, die Eingabe speziell zu erstellen gleicher Hashcode. Wenn Sie nun viele Suchvorgänge durchführen, kann es zu einem Denial-of-Service kommen. Es scheint, dass es ziemlich viel Code in der Wildnis gibt, der für diese Art von Angriffen anfällig ist, daher wurde beschlossen, dies auf der Java-Seite zu beheben.
Weitere Informationen finden Sie unter JEP-180 .
Ihre Frage enthält falsche Voraussetzungen.
Map
angemessen sein sollte, können Sie die Array-Größe nicht beliebig erhöhen, um Bucket-Kollisionen zu vermeiden. Es gibt sogar die theoretische Einschränkung, dass eine Array-Größe bei maximal 2³¹ liegen kann, während es 2²² mögliche Hash-Codes gibt. String
s sind ein offensichtliches Beispiel, aber sogar ein Point
mit zwei int
-Werten oder ein einfacher Long
-Schlüssel haben unvermeidbare Hash-Kollisionen. Sie können also häufiger vorkommen als Sie denken und hängt stark vom Anwendungsfall ab. Comparable
entsprechend implementiert, wird seine natürliche Reihenfolge verwendet. Die Beispiele, die Sie im Internet gefunden haben, verwenden bewusst den gleichen Hash-Code für Objekte, um die Verwendung der Comparable
-Implementierung zu demonstrieren, die andernfalls nicht angezeigt würde. Was sie auslösen, ist nur der letzte Ausweg der Implementierung.