Получить доступ

Как HashMap находит место для пары ключ-значение?

JuniorКоллекции
Ещё спрашивают так:
  • Как устроен HashMap?
  • Что такое коллизия в HashMap?
  • Почему get в HashMap работает за O(1)?
Коротко

По hashCode ключа вычисляется индекс корзины в массиве, внутри корзины ключи сравниваются через equals.

  • Коллизия — разные ключи в одной корзине: цепочка, при длине 8 и большой таблице — дерево
  • При заполнении выше 0.75 таблица удваивается (resize) с перераспределением

А ещё Отсюда требование: equals и hashCode у ключа должны быть согласованы и неизменны

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

HashMap: put, коллизия и resize

Подробно

HashMap — массив корзин (bucket). При put(key, value):

  1. вычисляется key.hashCode(), старшие биты подмешиваются к младшим;
  2. индекс корзины — hash & (n - 1), где n — размер массива (степень двойки);
  3. если корзина пуста — запись кладётся туда;
  4. если нет — это коллизия: идём по записям корзины и сравниваем ключи через equals; совпал — заменяем значение, нет — добавляем запись.

При чтении get(key) путь тот же, поэтому в среднем доступ — O(1).

Коллизии. Записи одной корзины образуют связный список. Если он вырастает до 8 элементов, а таблица не меньше 64 корзин, список превращается в красно-чёрное дерево (treeify) — худший случай становится O(log n) вместо O(n).

Расширение. Когда число записей превышает ёмкость × коэффициент загрузки (по умолчанию 0.75), массив удваивается и записи перераспределяются.

Требование к ключу: равные по equals объекты должны давать одинаковый hashCode, а поля, от которых они зависят, не должны меняться, пока ключ лежит в карте. Иначе запись «потеряется».

Пример

Map<String, Integer> stock = new HashMap<>();
stock.put("apple", 10);   // hash("apple") → корзина
stock.get("apple");       // та же корзина → equals → 10

Что хотят услышать

  • Хеш → индекс корзины → сравнение через equals.
  • Что такое коллизия и как она хранится (список, дерево).
  • Коэффициент загрузки и resize.
  • Требования к ключу: согласованные equals/hashCode, неизменность.

Частые ошибки

  • Ожидать от карты предсказуемого порядка обхода.
  • Использовать в качестве ключа объект без корректных equals и hashCode.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Вычисляет хеш ключа и по нему определяет корзину массива, внутри которой при необходимости сравнивает ключи
  • ✗Перебирает все элементы, сравнивая ключи по очереди
  • ✗Хранит пары отсортированными по ключу и ищет двоичным поиском
  • ✗Размещает пары в порядке добавления и запоминает их индексы

Что спросят дальше

  • Что происходит при коллизии ключей?
  • Почему изменение ключа после добавления ломает поиск?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем