Хеширование представляет собой типичный пример компромисса между временем и памятью. При отсутствии каких-либо ограничений на память любой поиск можно выполнить, просто обратившись к памяти с ключом в качестве индекса в (потенциально огромном) массиве. Однако, обычно этот идеал непостижим., т.к. при очень большом количестве возможный ключей объем необходимой памяти неподъемно велик. А если нет ограничения на время, можно задействовать лишь минимальное количество памяти, выполнить последовательный поиск в неупорядоченном массиве. Хеширование это способ использовать размуное количество как памяти, так и времени и найти баланс между этими двумя крайностями. Такой компромисс между памятью и временем в алгоримтах хеширования можно варьировать, настраивая параметры и не переписывая код. А для осознанного выбора значений этих параметров обычно используют классическую теорию вероятностей.
Сама суть в том, что использую хеш-функцию, можно преобразовать ключи в индексы массива. Если имеется массив который может вместить М пар ключ-значение, то хеш-функция должна преобразовывать любой заданный ключ в индекс в этом массиве. То есть от 0 до М-1 включая.
Три основных требования - хеш-функция должна быть согласованной: равные ключи должны давать одно и то же значение. Она должна эффективно вычисляться и она должна равномерно распределять ключи.
Одновременное удовлетворение всех жтих требований - задача для экспертов. Обычно, Java-программисты использующие хеширование, встроенное в Java, что функция hashCode() справляется, если нет свидетельств обратного.
Так что, если вас устраивает время и затраченные ресурсы, на поиск нужного элемента, у вас все хорошо и не о чем беспокоиться. Только если крайне важна высокая производительность, только тогда стоит более детально прорабатывать алгоритм расчета хеша.