我是Java的新手,我最近了解了hashCode()
。在the wikipedia article about Java hashCode()上,有一个hashCode()
方法的以下示例:
public class Employee {
int employeeId;
String name;
Department dept;
// other methods would be in here
@Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + employeeId;
hash = hash * 31 + name.hashCode();
hash = hash * 13 + (dept == null ? 0 : dept.hashCode());
return hash;
}
}
我知道乘以31和13会减少发生碰撞的机会,但是我不明白为什么将hash
初始化为1而不是初始化为employeeId
。最后,这只是在hashCode()
上加上17 * 31 * 13的效果,而这不会改变两个hashCode()值是否相等。
Bloch的“ Effective Java(第二版)”在第9项(第47和48页)中有一个非常相似的示例,但是他对这个可加常数的解释对我来说还是很神秘的。
编辑:此问题被标记为问题Why does Java's hashCode() in String use 31 as a multiplier?的重复项,该问题并不相同:它是在询问是否有任何理由比{}公式中的数字更喜欢数字31 hashCode()
中的{1}}。我的问题是,为什么在网上发现的许多String
实例中,所有对象的hashCode()
中都添加了一个常量。
实际上,hashCode()
中hashCode()
的示例在这里是相关的,因为在该示例中,没有添加常量。如果在我上面给出的示例中添加17 * 31 * 13起作用,为什么在计算String
的{{1}}时不添加这样的常量?
答案 0 :(得分:0)
以非零值开头在哈希值溢出或%不为2的幂的情况下在概念上有帮助,这导致比较溢出的值与未溢出的值相比,更多的位是不同的比较值。
小常量不如大常量有效,但可以使用更少的字节并更快。例如。 * 31更快,但效果可能不如* 109。
其区别取决于您的用例。
注意:即使确保您具有唯一的hashCode,也不能确保在使用数字选择存储区后不会发生冲突。