[英]Hashcode for objects with only integers
您如何以通用(和高性能)的方式实现哈希码,同时最小化具有 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;
}
}
}
对于具有 2 个或更多整数的对象,您能否以一种通用(和高性能)的方式实现没有冲突的哈希码?
当散列到 32 位(一个整数)由超过 32 位(如 2 个或更多整数)组成的东西时,从技术上讲不可能零冲突。
这是 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()
!
没有办法完全消除 hash 次碰撞。 您的方法基本上是减少冲突的首选方法。
创建零冲突的 hash 方法是不可能的。 hash 方法的想法是获取大量对象并将其映射到较小的整数集。 您能做的最好的事情就是尽量减少您在对象子集中发生的碰撞次数。
正如其他人所说,尽量减少碰撞比消除碰撞更重要——尤其是因为你没有说你的目标是多少桶。 与 2 个桶中的 5 个项目相比,与 1000 个桶中的 5 个项目零碰撞要容易得多,即使有很多桶。 1000 个桶和 1001 个桶的碰撞看起来可能非常不同。
另一件需要注意的事情是,您提供的 hash 很有可能甚至不是 HashMap 最终使用的那个。 例如,如果您查看OpenJDK HashMap 代码,您会发现您的密钥的哈希代码是通过一个私有的hash
方法(该链接中的第 264 行)重新哈希处理的。 因此,如果您正在努力创建一个精心构建的自定义 hash function 以减少碰撞(而不是简单的自动生成的碰撞),请确保您也了解谁将使用它,以及如何使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.