В java, когда я использую String в качестве ключа для Hashmap, я получаю немного другой результат, чем когда я использую хэш-код строки в качестве ключа в HashMap.
Любое понимание?
В java, когда я использую String в качестве ключа для Hashmap, я получаю немного другой результат, чем когда я использую хэш-код строки в качестве ключа в HashMap.
Любое понимание?
когда я использую строковый хэш-код в качестве ключа в HashMap.
Вы не должны использовать сам хеш-код в качестве ключа. Хэш-коды не должны быть уникальными — два неравных значения могут иметь один и тот же хеш-код. Вы должны использовать строку сама в качестве ключа. Затем карта сначала сравнит хэш-коды (чтобы быстро сузить возможные совпадения), а затем сравнит с equals
для подлинного равенства строк.
Конечно, это предполагает, что ваш код действительно такой, как ваш вопрос, например.
HashMap<String, String> goodMap = new HashMap<String, String>();
goodMap.put("foo", "bar");
HashMap<Integer, String> badMap = new HashMap<Integer, String>();
badMap.put("foo".hashCode(), "bar");
Если ваш код действительно выглядит так, просто используйте вместо него HashMap<String, String>
.
Из документации для Object.hashCode()
a> (выделено мной):
Общий контракт hashCode:
- Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java, метод hashCode должен постоянно возвращать одно и то же целое число, при условии, что никакая информация, используемая в сравнениях на равенство для объекта, не изменяется. Это целое число не обязательно должно оставаться постоянным от одного выполнения приложения к другому выполнению того же приложения.
- Если два объекта равны в соответствии с методом equals(Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат.
- Не требуется, чтобы, если два объекта не были равны в соответствии с методом equals(java.lang.Object), вызов метода hashCode для каждого из двух объектов должен давать разные целочисленные результаты. Однако Программист должен знать, что создание различных целочисленных результатов для неравных объектов может повысить производительность хеш-таблиц.
Конечно. Разные строки могут иметь один и тот же хэш-код, поэтому, если вы сохраните две такие строки в качестве ключей на карте, у вас будет две записи (поскольку строки разные). Если вы используете их хэш-код в качестве ключа, у вас будет только одна запись (поскольку их хэш-код одинаков).
Хэш-код не используется, чтобы определить, равны ли два ключа. Он используется только для назначения ведра клавише. Как только корзина найдена, каждый ключ, содержащийся в корзине, сравнивается с новым ключом с равными значениями, и ключ добавляется в корзину, если не удается найти равный ключ.
Проблема в том, что даже если два объекта разные, это не значит, что их хэш-коды тоже разные.
Два разных объекта могут иметь один и тот же хэш-код. Таким образом, вы не должны использовать их в качестве ключа HashMap.
Кроме того, поскольку хэш-коды, возвращаемые методом Object.hashCode()
, имеют тип int
, вы можете иметь только 2^32
различных значений. Вот почему у вас будут «коллизии» в зависимости от алгоритма хеширования для разных объектов.
Вкратце: -
!obj.equals(obj1)
не гарантирует, что obj.hashCode() != obj1.hashCode()
.
!obj.equals(obj1)
в последней строке, так как это важная часть.
- person Jon Skeet; 03.11.2012
HashCodes
может быть одинаковым или разным для одной и той же строки, поэтому будьте осторожны с этим. Может быть, поэтому вы получаете другой результат.
Вот еще один вопрос SO по этому поводу . См. принятый ответ Джона Скита.
Вы можете использовать хеш-код в качестве ключа, только если хеш-функция является идеальным хэшем (см. например, GPERF). Пока ваши ключевые объекты не находятся в памяти, вы правы, что будете экономить память.