Ответ 1
Понимание того, что делает для хорошей хеш-функции, сложно, так как на самом деле существует множество различных функций, которые используются и для немного разных целей.
Java-хэш-таблицы работают следующим образом:
- Они запрашивают ключевой объект для создания своего хэш-кода. Реализация метода
hashCode()
, скорее всего, будет отличаться переменным качеством (в худшем случае, возвращая постоянное значение!) И определенно не будет адаптирована к конкретной хеш-таблице, с которой вы работаете. - Затем они используют указанную выше функцию для смешивания бит бит, так что информация, содержащаяся в высоких битах, также перемещается вниз к младшим битам. Это важно, потому что следующий...
- Они берут мод хеш-кода (w.r.t. количество записей массива хеш-таблицы), чтобы получить индекс в массив цепей хеш-таблицы. Существует явная вероятность того, что массив хэш-таблицы будет иметь размер, эквивалентный мощности 2, поэтому смешение бит на шаге 2 важно, чтобы гарантировать, что они не просто отброшены.
- Затем они пересекают цепочку, пока не дойдут до записи с помощью равного ключа (в соответствии с методом
equals()
).
Чтобы завершить изображение, количество записей в массиве хэш-таблицы является непостоянным; если цепи становятся слишком длинными, массив заменяется новым более крупным массивом, и все становится перефразированным. Это относительно быстро и имеет хорошие показатели производительности для обычных шаблонов использования (например, много put()
, за которыми следуют серии get()
s).
Фактические используемые константы являются довольно произвольными (и, вероятно, они выбраны экспериментами с некоторым простым корпусом, включая такие вещи, как большие числа значений Integer
и String
), но их цель не такова: получение информации во всей разнице значений к большинству младших бит в значении гарантирует, что такая информация, которая присутствует в выводе hashCode()
, используется как можно лучше.
(Вы не сделали бы этого с совершенным хэшированием или криптографическим хэшированием, несмотря на аналогичные имена, у них очень разные стратегии реализации. Первый требует знания ключевого пространства, чтобы избежать/уменьшить столкновения, а последнему нужна информация для перемещения по всем направлениям, а не только к младшим битам.)