假设您需要速度而不需要*Set
类的开销,那么您可以编写H
如下:
/**
* Hashes a set of integers.
*
* @param list to hash
* @return hash code
*/
public static int H(int list[]) {
// XOR all the integers together.
int hashcode = 0;
for (int val : list) {
hashcode ^= val;
}
return hashcode;
}
不管顺序如何,都是一样的,效率比较高。
例如:
public static void main(String[] args) {
System.out.println(Integer.toHexString(H(new int[]{0xabcd,0x1234,0x1111})));
System.out.println(Integer.toHexString(H(new int[]{0x1234,0x1111,0xabcd})));
}
显示:
a8e8
a8e8
通过执行以下操作,这可以推广到不仅仅是int
s:
/**
* Hashes a set of objects.
*
* @param list to hash
* @return hash code
*/
public static int H(Object list[]) {
// XOR all the hashes together.
int hashcode = 0;
for (Object val : list) {
hashcode ^= val.hashCode();
}
return hashcode;
}
然后main
程序将不得不使用数组 ofInteger
而不是原语int
。
添加数字应该几乎一样快,并且可能会在 32 位范围内为您提供更好的分布。如果集合的元素已经均匀分布在范围内,那么 xor 可能会更好。
但是,使用这两种方法,您都可以轻松地使用整数制造碰撞。例如,使用添加方法;
{1000, 1001, 1002}
{0, 1, 3002}
这两个数组具有相同的H()
.
用异或法;
{0x1010, 0x0101}
{0x1111, 0x0000}
这两者具有相同的H()
.
同样,该0
元素是有问题的,因为无论有没有它,列表都将具有相同的哈希值。您可以通过在每次迭代中添加一个常数值来缓解这种情况。例如:
...
hashcode += val.hashCode() + CONSTANT;
...
或者通过包含元素的数量作为初始哈希码:
...
// XOR all the hashes together.
int hashcode = list.length;
...