HashMap
zawiera określoną liczbę zasobników. Używa hashCode
do określenia, do którego wiadra je umieścić. Dla uproszczenia wyobraź sobie to jako moduł.
Jeśli nasz hashcode to 123456 i mamy 4 segmenty, 123456 % 4 = 0
więc element trafia do pierwszego segmentu, Bucket 1.
Jeśli nasza funkcja hashcode jest dobra, powinna zapewniać równomierną dystrybucję, więc wszystkie zasobniki będą używane w pewnym stopniu po równo. W tym przypadku zasobnik używa połączonej listy do przechowywania wartości.
Ale nie można polegać na ludziach, którzy zaimplementują dobre funkcje skrótu. Ludzie często piszą słabe funkcje skrótu, co spowoduje nierównomierną dystrybucję. Możliwe jest również, że po prostu mieliśmy pecha z naszymi danymi wejściowymi.
Im mniej równomierny jest ten rozkład, tym dalej przechodzimy od operacji O (1) i tym bliżej zbliżamy się do operacji O (n).
Wdrożenie Hashmap próbuje to złagodzić, organizując niektóre segmenty w drzewa zamiast połączonych list, jeśli zasobniki stają się zbyt duże. Po to TREEIFY_THRESHOLD = 8
jest. Jeśli wiadro zawiera więcej niż osiem elementów, powinno stać się drzewem.
To drzewo jest drzewem czerwono-czarnym. Najpierw jest sortowany według kodu skrótu. Jeśli kody skrótu są takie same, używa compareTo
metody, Comparable
jeśli obiekty implementują ten interfejs, w przeciwnym razie kod skrótu tożsamości.
Jeśli wpisy zostaną usunięte z mapy, liczba wpisów w zasobniku może się zmniejszyć, tak że ta struktura drzewa nie będzie już potrzebna. Do tego UNTREEIFY_THRESHOLD = 6
służy. Jeśli liczba elementów w zasobniku spadnie poniżej sześciu, równie dobrze możemy wrócić do korzystania z listy połączonej.
Wreszcie jest MIN_TREEIFY_CAPACITY = 64
.
Kiedy mapa skrótów rośnie, automatycznie zmienia swój rozmiar, aby mieć więcej zasobników. Jeśli mamy małą mapę mieszania, prawdopodobieństwo, że otrzymamy bardzo pełne segmenty, jest dość wysokie, ponieważ nie mamy tak wielu różnych segmentów, w których można umieścić rzeczy. Znacznie lepiej jest mieć większą mapę mieszania z większą liczbą mniejszych zasobników. Ta stała w zasadzie mówi, że nie należy zaczynać przekształcania wiader w drzewa, jeśli nasza mapa skrótów jest bardzo mała - zamiast tego powinna najpierw zmienić rozmiar na większy.
Aby odpowiedzieć na pytanie dotyczące wzrostu wydajności, te optymalizacje zostały dodane w celu poprawy najgorszego przypadku. Spekuluję tylko, ale prawdopodobnie zauważysz zauważalną poprawę wydajności z powodu tych optymalizacji, jeśli twoja hashCode
funkcja nie była zbyt dobra.
String
, mają znacznie większą przestrzeń wartości niżint
kod skrótu, dlatego kolizje są nieuniknione. Teraz zależy to od rzeczywistych wartości, takich jak rzeczywiste wartości,String
które umieścisz na mapie, czy uzyskasz równomierny rozkład, czy nie. Zła dystrybucja może wynikać po prostu z pecha.