作者:PHP小龙 | 来源:互联网 | 2023-05-17 11:28
我有一个类的哈希码实现,哈希码实现与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,这大于为上述数据集计算的哈希码= 50268236873,所以有溢出.使用long作为hashCode值的类型有什么后果吗?
谢谢
Nohsib
编辑:
我正在使用HashSet,在阅读了发布的答案后,我查找了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正在替换exisintg记录.
1> L. Blanc..:
通常,哈希码不保证唯一性.HashMap实现通常通过在幕后存储列表来处理冲突,但它们包括一个检查,确保您不会将列表中的所有内容都作为匹配项,只是那些真正匹配的项.
换句话说,如果你执行map.get("foo")并且存在冲突,则哈希映射将检查每个结果(未哈希)以查看它是否真正匹配"foo".然后它只返回完全匹配.
还要注意,虽然哈希码的契约声明任何两个对equals()响应为true的对象应该具有相同的哈希码,但相反的情况不一定如此.
@Nohsib - 你误解了哈希码的契约 - 它提供了哈希,而不是唯一的ID.如果您正在使用使用哈希码的Java集合,那么只要您正确地实现了等号,它们就可以解决如何在没有重复和冲突的情况下存储事物.您的代码的真正问题不是哈希码的实现,而是您构建集合的方式 - 您是否愿意共享它?