Другой вопрос спрашивает, есть ли какие-то базовые вещи низкого уровня, которые должны знать все программисты, и я думаю, что поиск хеша - один из них. Так что вот так.
Хеш-таблица (обратите внимание, что я не использую фактическое имя класса) - это в основном массив связанных списков. Чтобы найти что-то в таблице, вы сначала вычисляете хеш-код этого чего-то, а затем модифицируете его по размеру таблицы. Это индекс в массиве, и вы получите связанный список по этому индексу. Затем вы перемещаетесь по списку, пока не найдете свой объект.
Поскольку извлечение массива равно O (1), а обход связанного списка - O (n), вам нужна хеш-функция, которая создает как можно более случайное распределение, чтобы объекты хэшировались в разные списки. Каждый объект может вернуть значение 0 в качестве своего хеш-кода, и хеш-таблица все равно будет работать, но по сути это будет длинный связанный список в элементе 0 массива.
Вы также обычно хотите, чтобы массив был большим, что увеличивает шансы на то, что объект будет в списке длиной 1. Например, Java HashMap увеличивает размер массива, когда количество записей в карте > 75% от размера массива. Здесь есть компромисс: вы можете иметь огромный массив с очень небольшим количеством записей и ненужной памятью, или меньший массив, где каждый элемент в массиве представляет собой список с> 1 записями, и трата времени тратится. Идеальный хеш назначил бы каждому объекту уникальное место в массиве, без потери места.
Термин «идеальный хеш» - это реальный термин, и в некоторых случаях вы можете создать хеш-функцию, которая предоставляет уникальный номер для каждого объекта. Это возможно только тогда, когда вы знаете множество всех возможных значений. В общем случае вы не можете достичь этого, и будут некоторые значения, которые возвращают тот же хэш-код. Это простая математика: если у вас есть строка длиной более 4 байтов, вы не можете создать уникальный 4-байтовый хеш-код.
Один интересный момент: массивы хешей обычно имеют размер, основанный на простых числах, чтобы дать наилучшую возможность случайного распределения при изменении результатов независимо от того, насколько случайными являются хеш-коды.
Редактировать на основе комментариев:
1) Связанный список - не единственный способ представления объектов, имеющих одинаковый хеш-код, хотя этот метод используется в HDMap JDK 1.5. Несмотря на то, что он менее эффективен в отношении памяти, чем простой массив, он, возможно, создает меньше оттока при перефразировании (поскольку записи можно отсоединить от одного сегмента и связать с другим).
2) Начиная с JDK 1.4, класс HashMap использует массив размером в степень 2; до этого он использовал 2 ^ N + 1, который, я считаю, прост для N <= 32. Это не ускоряет индексацию массива как таковую, но позволяет вычислять индекс массива с побитовым И вместо деления, как отметил Нил Коффи. Лично я бы усомнился в этом как в преждевременной оптимизации, но, учитывая список авторов в HashMap, я предполагаю, что есть реальная выгода. </p>