Почему моя Java HashMap
не работает? Мой объект обладает тем свойством, что равенство .equals
подразумевает равенство hashCode
.
Вы можете предположить, что я изменяю поле объекта после добавления объекта в HashMap
.
Почему моя Java HashMap
не работает? Мой объект обладает тем свойством, что равенство .equals
подразумевает равенство hashCode
.
Вы можете предположить, что я изменяю поле объекта после добавления объекта в HashMap
.
Можно предположить, что я изменяю поле объекта после добавления объекта в HashMap.
Именно поэтому.
Примечание: следует проявлять большую осторожность, если изменяемые объекты используются в качестве ключей карты. Поведение карты не указано, если значение объекта изменяется таким образом, что это влияет на сравнение на равенство, в то время как объект является ключом в карте.
«Не указано» означает «может не работать», так что не удивляйтесь, если это не сработает.
Если вы мутируете (изменяете) объекты после добавления их в HashMap
, ваши объекты окажутся не в том сегменте. Это связано с тем, что даже если объект изменился, он не "повторно заполняется" в (новую) правильную корзину после внесения изменений.
Таким образом, такие методы, как remove
, не смогут найти ваш объект, потому что объект находится в устаревшем ведре.
Что действительно приводит меня в чувство (для меня), так это то, что когда объект изначально добавляется в HashMap
, хэш-значение (int) сохраняется вместе с Entry. Это означает, что хэш является относительно статичным свойством, которое редко (никогда) не обновляется.
Возможные обходные пути включают в себя:
Вероятно, это сработает, если вы переберете каждую запись в hashmap
и создадите новую HashMap
из этих записей. Это, вероятно, плохо с точки зрения производительности, но, вероятно, самое правильное, что можно сделать.
Не включайте поле, которое изменяется, в вашу функцию hashCode
. Хотя это и не очень хорошо (использование неопределенного поведения компилятора в лучшем случае является рискованным делом), оно, как правило, работает, потому что у вас будут только коллизии, которые влияют только на производительность, а не на правильность. Вам по-прежнему необходимо включить проблемное поле в метод .equals(Object obj)
, иначе вы можете удалить неправильные объекты.
Алгоритмическое решение: Найдите способ сохранить другую часть данных в объекте, который действует как постоянный ключ. Например, в моем приложении я отслеживал «возраст» объекта с помощью целочисленного поля. Каждый раз, когда я достигал определенного количества времени в своем приложении, я увеличивал возраст всех ключей. Если что-то было старше 50 единиц времени, то я мог разумно выбросить пару ключ-значение. В качестве альтернативы я мог бы изменить объект, чтобы сохранить «время рождения» объекта. То есть, если приложению было 1000 единиц времени, когда объект был создан, я бы сохранил число 1000. Затем, чтобы определить возраст объекта, я мог бы сравнить текущее «время» со временем рождения и выбросить объект, если разница была> 50.