我有一个类的哈希码实现,哈希码实现与 eclipse 生成的内容一致,也是此处讨论的最普遍接受的做法
这是我的哈希码实现(此方法中使用的所有 Id 构成对象的键):
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 :
Record@2c0781cd[uId=54046,rId=10967,bId=177,reId=1728,cId=50194]
Record being inserted into the collection :
Record@20dad050[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,大于为上述数据集计算的 hashcode = 50268236873,因此存在溢出. 使用 long 作为 hashCode 值的类型有什么后果吗?
感谢
Nohsib
编辑 :
我正在使用 HashSet 并在阅读完发布的答案后,我查看了 equals 实现,如下所示,我认为因为在 equals 中我检查两个对象的 hashCodes 是否相同并使用它来确定它们是否是相同的对象导致了这个问题。
你们中的任何人都可以证实这一点吗?
@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;
}
解决方案:我的 equals 方法实现是错误的,因为我使用 hashCode 来确定两个对象是否相等。纠正 equals 方法实现解决了我的问题是 hashset 正在替换现有记录。