Вопрос с собеседования · Java

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

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

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

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

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

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

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

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования