У меня есть реализация Hashcode для класса и реализации Hashcode согласуется с тем, что затмение генерирует, а также наиболее широко распространенной практикой, как обсуждалось hereКак обеспечить, чтобы hashcode() не разрешал одно и то же значение в Java?
Вот моя реализация хэш-код (Все Идентификаторы используются в данном методе являются ключом для объекта):
public int hashCode() {
final int prime = 31;
int hashCode = 1;
if(uId != null){
hashCode = prime * hashCode + uId.hashCode();
}
if(rId != null){
hashCode = prime * hashCode + rId.hashCode();
}
if(bId != null){
hashCode = prime * hashCode + bId.hashCode();
}
if(reId != null){
hashCode = prime * hashCode + reId.hashCode();
}
if(cId != null){
hashCode = prime * hashCode + cId.hashCode();
}
return hashCode;
}
Я побежал в сценарий, где я тестирование с очень большим набором данных и моя коллекция не имела ожидаемое количество объектов этого класса. При пристальном рассмотрении приведенные ниже два набора данных привели к тому же хэш-коду: 50268236873 и, следовательно, запись заменялась последней, которая была добавлена в коллекцию, так как их хэш-коды были одинаковыми.
Existing record :
[email protected][uId=54046,rId=10967,bId=177,reId=1728,cId=50194]
Record being inserted into the collection :
[email protected][uId=53806,rId=18389,bId=177,reId=19026,cId=50194]
Both of these had the hashCode value = 50268236873
Итак, вопросы:
1] Это ясно случай, когда хэш-коды двух различных объектов имеют одинаковое значение. Итак, как обеспечить, чтобы это не происходило с каким-либо набором данных? Должна ли раскраска быть больше?
2] Если мы внимательно рассмотрим переменную hashCode в реализации, это тип данных int, наибольшее значение которого составляет 2^31 - 1 = 2147483647, что больше того, что хэш-код, который вычисляется для указанного набора данных = 50268236873, так что является переполнением. Есть ли какое-либо следствие долгое использование типа значения hashCode?
благодаря
Nohsib
Edit:
Я использую HashSet и после прочтения ответов вывешенных, я посмотрел на реализации Equals, как показано ниже, и я думаю, потому что в равном я проверяю посмотрите, являются ли хэш-коды двух объектов одинаковыми и используют это, чтобы определить, являются ли они одними и теми же объектами, что приводит к этой проблеме.
Может ли кто-нибудь из вас подтвердить это?
@Override
public boolean equals(Object paramObject) {
boolean equals = false;
if (paramObject != null) {
ACRecord other = (ACRecord) paramObject;
if ((this.hashCode() == other.hashCode()) // I think this is where I am going wrong
|| (this.uId.equals(other.getUId())
&& this.rId.equals(other.getRId())
&& this.reId.equals(other.getReId())
&& this.bId.equals(other.getBId())
&& this.cId.equals(other.getCId))) {
equals = true;
}
}
return equals;
}
Решения: My равно реализация методы была ошибочной, так как я использовал хэш-код, чтобы определить, если два объекта были equal.Correcting реализация методы равно решена моя проблема была HashSet заменяла запись exisintg.
Какая была коллекция?Только метод equals используется в коллекциях для обнаружения дубликатов, хеши используются только для ускорения процесса. – Zielu
Кроме того, в вашем хеш-коде есть (спорная) логическая ошибка. Возможно, вам придется рассмотреть случай, когда каждый идентификатор равен NULL, если вы хотите сохранить относительное положение каждого идентификатора в хеше. Таким образом, каждое предложение if может быть лучше выполнено как 'hashCode = prime * hashCode + (id == null? 0: id.hashCode());'. В качестве бонуса это облегчает чтение метода. –
@Zielu: Я использую HashSet. – Nohsib