Сначала ответь вслух
Скажи ответ вслух хотя бы пару минут, потом открой эталон и сравни. Эталон открыт всем и не требует входа.
Показать ответ
Эталонный ответ
HashMap берёт hashCode() ключа и перемешивает старшие биты с младшими: h ^ (h >>> 16). Длина таблицы всегда степень двойки, поэтому индекс корзины считается быстро: (n - 1) & hash.
В корзине элементы лежат списком. При поиске HashMap сравнивает сначала сохранённый хеш, затем ссылку и equals. Если в корзине больше 8 элементов, а таблица не меньше 64 корзин, список превращается в красно-чёрное дерево.
Когда элементов становится больше ёмкость × loadFactor (по умолчанию 16 × 0,75 = 12), таблица удваивается. Каждый элемент либо остаётся в своей корзине, либо переезжает ровно на старую длину вперёд: решает один бит хеша.
static int hash(Object key) {
int h;
return key == null ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
int index = (table.length - 1) & hash(key);Как у тебя получилось?
Уточняющие вопросы
Так обычно копают глубже. Раскрой строку, когда ответишь вслух.
Уточнение 1-го уровня: Зачем перемешивать старшие биты с младшими?
Ответ уровня Middle
Индекс берёт только младшие биты. Без перемешивания ключи, которые отличаются только старшими битами, падали бы в одну корзину.
Уточнение 2-го уровня: Как создать HashMap под заранее известное число элементов?
Ответ уровня Middle
Ёмкость должна быть больше ожидаемое / 0,75, иначе будет лишнее расширение. С Java 19 есть HashMap.newHashMap(n), который считает это сам.
Типичные ошибки
- Говорить, что корзина становится деревом сразу после 8 элементов: нужна ещё таблица от 64 корзин.
- Путать ёмкость таблицы с числом элементов в size().
Первоисточники
Быстрые задания по теме
Проверь себя
Задание 1 из 3Два разных ключа дали одинаковый hashCode. Что сделает HashMap?