JAVAPROGLIB Telegram 6993
👀 Внутреннее устройства HashMap

HashMap — один из базовых и в то же время самых хитро устроенных контейнеров в JDK. На поверхности простая структура «ключ–значение», но под капотом она сочетает массивы, списки и даже деревья, чтобы оставаться быстрой в разных сценариях нагрузки.

📦 Базовая структура

HashMap хранит данные в массиве бакетов (Node<K,V>[] table). Каждый бакет — это «корзина» для элементов, чей hashCode после хеширования и применения & (n-1) (где n — длина массива) указывает на конкретный индекс.

🔑 Хэш и распределение

1. Вызов hashCode() у ключа.
2. Дополнительное хеширование (spread), чтобы снизить коллизии из-за плохой реализации hashCode.
3. Индекс бакета = hash & (table.length - 1).

🌊 Коллизии

Если несколько ключей попали в один бакет:

— до Java 8 это всегда был связанный список (linked list),

— начиная с Java 8: при росте числа элементов в бакете больше 8 и достаточном размере таблицы он превращается в сбалансированное красно-чёрное дерево. Это резко ускоряет поиск в «плохих» случаях (с O(n) до O(log n)).

⚡️ Ресайзинг

Когда количество элементов превышает capacity * loadFactor (по умолчанию 0.75), создаётся новый массив в 2 раза больше, все элементы перехешируются и раскладываются по новым бакетам. Это дорогостоящая операция, но благодаря амортизации остаётся приемлемой.

📊 Производительность


— Поиск/вставка/удаление в среднем: O(1).

— В худшем случае (плохой hashCode + коллизии): O(log n) благодаря деревьям.

⚖️ Важные нюансы


— Ключи неупорядочены. Для упорядоченности есть LinkedHashMap.

— HashMap не потокобезопасен. Для многопоточной среды нужен ConcurrentHashMap или синхронизация.

— Хорошо реализованный hashCode и equals критичны, иначе получите «забитые» бакеты и деградацию.

🧮 loadFactor и capacity


— Capacity — размер массива бакетов. По умолчанию 16.

— LoadFactor — коэффициент заполнения. По умолчанию 0.75.

Почему именно 0.75? Это компромисс: выше → меньше памяти, но больше коллизий; ниже → быстрее доступ, но больше памяти уходит впустую. Capacity всегда степень двойки, чтобы можно было вычислять индекс через hash & (n-1) вместо затратного %.

🔄 Итераторы и fail-fast

Если во время обхода карта меняется (кроме iterator.remove()), бросается ConcurrentModificationException. Под капотом это работает через счётчик модификаций (modCount), который проверяется в каждом next().

🌳 Деревья в деталях

Коллизии превращаются в красно-чёрное дерево, если размер списка в бакете > 8 и общее количество бакетов ≥ 64. Обратно в список (untreeify) при падении количества элементов < 6. Это сделано, чтобы не тратить память и CPU на лишнюю балансировку при малых размерах.

🔗 Документация: OpenJDK — HashMap source

Ставьте 🔥, если хотите такой же пост по другим коллекциям.

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24👍81👏1



tgoop.com/javaproglib/6993
Create:
Last Update:

👀 Внутреннее устройства HashMap

HashMap — один из базовых и в то же время самых хитро устроенных контейнеров в JDK. На поверхности простая структура «ключ–значение», но под капотом она сочетает массивы, списки и даже деревья, чтобы оставаться быстрой в разных сценариях нагрузки.

📦 Базовая структура

HashMap хранит данные в массиве бакетов (Node<K,V>[] table). Каждый бакет — это «корзина» для элементов, чей hashCode после хеширования и применения & (n-1) (где n — длина массива) указывает на конкретный индекс.

🔑 Хэш и распределение

1. Вызов hashCode() у ключа.
2. Дополнительное хеширование (spread), чтобы снизить коллизии из-за плохой реализации hashCode.
3. Индекс бакета = hash & (table.length - 1).

🌊 Коллизии

Если несколько ключей попали в один бакет:

— до Java 8 это всегда был связанный список (linked list),

— начиная с Java 8: при росте числа элементов в бакете больше 8 и достаточном размере таблицы он превращается в сбалансированное красно-чёрное дерево. Это резко ускоряет поиск в «плохих» случаях (с O(n) до O(log n)).

⚡️ Ресайзинг

Когда количество элементов превышает capacity * loadFactor (по умолчанию 0.75), создаётся новый массив в 2 раза больше, все элементы перехешируются и раскладываются по новым бакетам. Это дорогостоящая операция, но благодаря амортизации остаётся приемлемой.

📊 Производительность


— Поиск/вставка/удаление в среднем: O(1).

— В худшем случае (плохой hashCode + коллизии): O(log n) благодаря деревьям.

⚖️ Важные нюансы


— Ключи неупорядочены. Для упорядоченности есть LinkedHashMap.

— HashMap не потокобезопасен. Для многопоточной среды нужен ConcurrentHashMap или синхронизация.

— Хорошо реализованный hashCode и equals критичны, иначе получите «забитые» бакеты и деградацию.

🧮 loadFactor и capacity


— Capacity — размер массива бакетов. По умолчанию 16.

— LoadFactor — коэффициент заполнения. По умолчанию 0.75.

Почему именно 0.75? Это компромисс: выше → меньше памяти, но больше коллизий; ниже → быстрее доступ, но больше памяти уходит впустую. Capacity всегда степень двойки, чтобы можно было вычислять индекс через hash & (n-1) вместо затратного %.

🔄 Итераторы и fail-fast

Если во время обхода карта меняется (кроме iterator.remove()), бросается ConcurrentModificationException. Под капотом это работает через счётчик модификаций (modCount), который проверяется в каждом next().

🌳 Деревья в деталях

Коллизии превращаются в красно-чёрное дерево, если размер списка в бакете > 8 и общее количество бакетов ≥ 64. Обратно в список (untreeify) при падении количества элементов < 6. Это сделано, чтобы не тратить память и CPU на лишнюю балансировку при малых размерах.

🔗 Документация: OpenJDK — HashMap source

Ставьте 🔥, если хотите такой же пост по другим коллекциям.

🐸 Библиотека джависта

#CoreJava

BY Библиотека джависта | Java, Spring, Maven, Hibernate




Share with your friend now:
tgoop.com/javaproglib/6993

View MORE
Open in Telegram


Telegram News

Date: |

In 2018, Telegram’s audience reached 200 million people, with 500,000 new users joining the messenger every day. It was launched for iOS on 14 August 2013 and Android on 20 October 2013. A vandalised bank during the 2019 protest. File photo: May James/HKFP. Invite up to 200 users from your contacts to join your channel As the broader market downturn continues, yelling online has become the crypto trader’s latest coping mechanism after the rise of Goblintown Ethereum NFTs at the end of May and beginning of June, where holders made incoherent groaning sounds and role-played as urine-loving goblin creatures in late-night Twitter Spaces. Some Telegram Channels content management tips
from us


Telegram Библиотека джависта | Java, Spring, Maven, Hibernate
FROM American