为什么要向hashCode()添加一个常量?

时间:2018-10-03 04:53:36

标签: java hash hashcode hash-collision

我是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}}时不添加这样的常量?

1 个答案:

答案 0 :(得分:0)

以非零值开头在哈希值溢出或%不为2的幂的情况下在概念上有帮助,这导致比较溢出的值与未溢出的值相比,更多的位是不同的比较值。

小常量不如大常量有效,但可以使用更少的字节并更快。例如。 * 31更快,但效果可能不如* 109。

其区别取决于您的用例。

注意:即使确保您具有唯一的hashCode,也不能确保在使用数字选择存储区后不会发生冲突。