如何以一般(并且高效)的方式实现哈希码,同时最大限度地减少具有2个或更多整数的对象的冲突?
更新:正如许多人所说的那样,你无法彻底消除崩溃(诚实地没有想到它)。所以我的问题应该是如何以适当的方式最小化碰撞,编辑以反映这一点。
使用NetBeans的自动生成失败;例如:
public class HashCodeTest {
@Test
public void testHashCode() {
int loopCount = 0;
HashSet<Integer> hashSet = new HashSet<Integer>();
for (int outer = 0; outer < 18; outer++) {
for (int inner = 0; inner < 2; inner++) {
loopCount++;
hashSet.add(new SimpleClass(inner, outer).hashCode());
}
}
org.junit.Assert.assertEquals(loopCount, hashSet.size());
}
private class SimpleClass {
int int1;
int int2;
public SimpleClass(int int1, int int2) {
this.int1 = int1;
this.int2 = int2;
}
@Override
public int hashCode() {
int hash = 5;
hash = 17 * hash + this.int1;
hash = 17 * hash + this.int2;
return hash;
}
}
}
答案 0 :(得分:1)
你能否以一般(和高效)的方式实现hashcode而不用 具有2个或更多整数的对象的colisions。
技术上,当散列到32位(一个整数)时,由于超过32位(如2个或更多整数)而产生零冲突。
答案 1 :(得分:1)
这是eclipse自动生成的内容:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + int1;
result = prime * result + int2;
return result;
}
使用此代码,您的测试用例通过......
PS:不要忘记实施equals()
!
答案 2 :(得分:0)
无法完全消除哈希冲突。您的方法基本上是最小化碰撞的首选方法。
答案 3 :(得分:0)
创建零冲突的哈希方法是不可能的。哈希方法的想法是你需要一大组对象并将它映射到一组较小的整数。您可以做的最好的事情是最大限度地减少您在对象子集中获得的碰撞次数。
答案 4 :(得分:0)
正如其他人所说的那样,最大限度地减少碰撞消除它们更为重要 - 特别是因为你没有说出你想要的铲斗数量。如果在2个桶中有5个项目,那么在1000个桶中与5个项目进行零冲突要容易得多!即使有很多桶,你的碰撞看起来也会有很大不同,1000桶和1001桶。
另外需要注意的是,您提供的哈希很可能不会是HashMap最终使用的哈希。例如,如果您查看OpenJDK HashMap code,您会看到您的密钥'hashCodes是通过私有hash
方法(该链接中的第264行)进行重新散列的。因此,如果您经历了创建精心构造的自定义散列函数以减少冲突(而不仅仅是简单的,自动生成的冲突)的麻烦,请确保您也了解谁将使用它,以及如何使用它。