Коллизии

Базовый Algorithms
≈ 2 мин чтения

Когда разные ключи получают один хеш

Коллизия возникает, когда разные ключи дают один и тот же хеш или в итоге попадают в одну корзину. Это не ошибка хеш-функции и не редкое исключение: количество возможных ключей огромно, а количество хешей и корзин конечно, поэтому полностью исключить коллизии нельзя.

record Key(int value) {
    @Override
    public int hashCode() {
        return 1;
    }
}

Map<Key, String> map = new HashMap<>();
map.put(new Key(10), "ten");
map.put(new Key(20), "twenty");

Оба ключа имеют одинаковый hashCode(), но они не равны друг другу. Корректная хеш-таблица обязана сохранить обе записи и при поиске различить их по самим ключам.

Два основных способа обработки

Один подход — цепочки (separate chaining): каждая корзина может содержать несколько записей. После перехода в нужную корзину таблица сравнивает ключ с находящимися там ключами. Если распределение хорошее, таких сравнений остаётся мало.

Другой подход — открытая адресация: все записи находятся прямо во внутреннем массиве, а при занятой позиции алгоритм по определённому правилу ищет другую свободную позицию. У этих подходов разные детали реализации, но цель одна — не потерять записи, которые претендуют на одно место.

Почему важна заполненность таблицы

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

При хорошем распределении и контролируемой загрузке операции остаются ожидаемо близкими к O(1). Если множество ключей постоянно попадает в одно место, объём работы растёт и в худшем случае может приблизиться к O(n).

Коллизия и повторный ключ — разные ситуации. При коллизии ключи различаются и обе записи должны существовать. При повторной вставке того же ключа структура типа Map обычно обновляет связанное с ним значение.