有时我需要通过组合其几个实例成员的hashCodes来实现obj的hashCode()方法.例如,如果组合obj有成员a,b和c,我经常看到ppl将其实现为
int hashCode(){
return 31 * 31 * a.hashCode() + 31 * b.hashCode() + c.hashCode();
}
Run Code Online (Sandbox Code Playgroud)
这个神奇的数字31来自哪里?它是4字节的长度还是只是素数?
有没有其他优选/标准的方法来实现hashCode()?
请参阅Effective Java的配方.这只是最好的消息来源.
使用素数只是为了在不知道域的情况下尝试获得相当好的分布.溢出到相同的值需要一段时间.如果我没记错的话,值31非常随意.
根据布洛赫(他使用17作为初始值,37作为常数乘数):
使用非零初始值(...),因此哈希值将受哈希值(...)为零的初始字段的影响.如果将零用作初始值(...),则整个散列值将不受任何此类初始字段的影响,这可能会增加冲突.值17是任意的.
...
选择乘法器37是因为它是一个奇数素数.如果它是偶数并且乘法溢出,则信息将丢失,因为乘以2相当于移位.使用素数的优点不太清楚,但为此目的使用素数是传统的.
一个很好的选择是番石榴的Objects.hashCode方法.它需要任意数量的参数并根据它们创建一个哈希码:
@Override public int hashCode() {
return Objects.hashCode(a, b, c);
}
Run Code Online (Sandbox Code Playgroud)