Что произойдет, если два разных объекта имеют один и тот же хэш-код?
Я понимаю, что два неравных объекта могут иметь один и тот же хэш-код. Как это можно было бы обрабатывать при добавлении или извлечении из java файла HashMap?
Ответы
Ответ 1
Они будут добавлены в один и тот же ковш, и equals()
будет использоваться для их различения.
Каждое ведро может содержать список объектов с одним и тем же хеш-кодом.
В теории вы можете вернуть то же целое число, что и хэш-код для любого объекта данного класса, но это будет означать, что вы потеряете все преимущества производительности хэш-карты и, по сути, сохраните объекты в списке.
Ответ 2
В HashMap ключи вместе со своими ассоциативными значениями хранятся в связанном списке node в ковше, и ключи по существу сравниваются в hashmap с использованием метода equals(), а не с помощью hashcode.
hm.put("a","aValue"); // Suppose hashcode created for key "a" is 209
hm.put("b","bValue"); // Here hashcode created for key "b" is 209 as well.
- Если
a.equals(b)
возвращает true
, bValue
заменит aValue
и будет возвращен bValue
.
- Если
a.equals(b)
возвращает false
, в списке ведер будет создан другой node, поэтому при вызове get("b")
вы получите bValue
, так как a.equals(b)
есть false
.
Ответ 3
HashMap работает над концепцией хэширования и индексирования.
Внутренне HashMap сохраняет значения в массиве узлов.
Каждый node ведет себя как LinkedList.
Каждый node связанного списка имеет 4 значения:
-
int hash
-
K key
-
V value
-
Node<K, V> next
HashMap Внутренняя структура:
![HashMap Внутренняя структура изображения]()
При вставке значения в HashMap генерируется первый хэш-код ключа и на основе некоторого алгоритма он вычисляет индекс.
Таким образом, наше значение будет храниться в определенном индексе с hashcode, ключом, значением и адресом следующего элемента.
При извлечении значения из HashMap первый хэш-код будет генерировать и затем индексировать (так же, как и во время вставки). Получая значение из индекса, сначала он проверяет hashcode, если hashcode будет соответствовать, тогда только он будет проверять ключ от node с помощью метода equals.
Если ключ будет соответствовать, то он вернет это значение, иначе он будет проверять следующий node с тем же хэш-кодом.
Ответ 4
В этом случае вы можете использовать IdentityHashMap, где разные объекты с одинаковым хешем считаются разными в зависимости от их идентификаторов.
Ответ 5
Если два неравных объекта имеют одно и то же значение хэша, это вызывает столкновение в хеш-таблице, потому что оба объекта хотят находиться в одном слоте (иногда называемом ведром). Алгоритм хэша должен разрешать такие столкновения. Возвращаясь к исчезающим воспоминаниям о курсах алгоритмов моего колледжа, я помню три основных способа сделать это:
- Найдите следующий пустой слот в хеш-таблице и поместите туда объект. Плюсы: легко реализовать, минусы: могут привести к кластеризации объектов и ухудшить производительность, емкость может быть превышена.
- У вас есть вспомогательная хеш-функция, когда есть конфликт: Плюсы: обычно быстрая, минус: нужно написать вторую хеш-функцию и все равно столкнуться, а емкость может быть превышена
- Сделать связанный список объектов из конфликтного слота хеш-таблицы. Плюсы/минусы: обычно быстрые для достойной хеш-функции и коэффициенты нагрузки, но могут ухудшаться до линейного поиска в худшем случае.
Я думаю, что классы хэша Java используют третий метод, но они могут использовать комбинированный подход. Ключ к хорошему хэшированию заключается в том, чтобы убедиться, что хеш-таблица имеет достаточно большую емкость и писать хорошие хэш-функции. Хэш-таблица, в которой есть только столько ведер, что объекты, которые она удерживает, вероятно, будет иметь конфликты. Обычно вы хотите, чтобы хэш-таблица была примерно в два раза больше, чем количество объектов, которые она хранит. Java HashMap будет расти по мере необходимости, но вы можете придать ему начальную емкость и коэффициент загрузки, если хотите.
Хеш-функция зависит от программиста. Вы можете просто вернуть 0 для всех объектов, но это будет означать, что хеширование (как хранилище, так и извлечение) станет O (n) вместо O (1)... или в несрочных терминах, это будет медленным.
Ссылка: http://www.coderanch.com/t/540275/java/java/objects-hashcode-HashMap-retrieve-objects