Проблема в том, что хеш-код объекта R
может изменить . Это нарушение договора, которому должен подчиняться метод hashCode()
.
Чтобы понять, почему это важно, вам нужно понять, как работает хеш-таблица. Java HashSet имеет в своей основе массив списков записей. Когда вы помещаете объект в хеш-таблицу, он сначала вычисляет хеш-код объекта. Затем он уменьшает хеш-код до индекса в массиве, вычисляя
index = hashcode % array.length
Затем он ищет цепочку, начиная с array[index]
, и, если объект отсутствует в списке, он добавляет его.
И чтобы проверить, содержит ли HashSet объект, он выполняет те же вычисления и ищет ту же цепочку хешей.
Однако, если вы сделаете что-то с объектом, чтобы заставить его хеш-код измениться, пока он находится в таблице, то алгоритм, приведенный выше, будет (обычно) искать объект в цепочке, отличной от той, в которую он был первоначально добавлен. И конечно не найдет.
Чистый результат состоит в том, что HashSet будет вести себя аномально, если контракт хеш-кода будет нарушен для какого-либо объекта, пока объект является членом набора.
Вот что говорит Java 7 javadoc (см. Java.jang.Object # hashcode ()):
"Общий контракт хэш-кода:
Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число при условии, что никакая информация, используемая в сравнениях сравнения объекта, не изменяется , Это целое число не обязательно должно быть согласованным при выполнении одного приложения другим исполнением того же приложения.
...
"не предоставил никакой информации ..." Я думаю, что это работает, только если есть правило о том, что объектные хеш-коды не должны меняться, пока они находятся в хеш-таблице. К сожалению, это правило не указано ни в одном месте, где вы ожидаете его найти. Ошибка документации?
Может быть, мы должны назвать требование не менять хеш-коды "словесным контрактом"? : -)