散列函数应该尽可能的把不行等的实例均匀的分布到所有可能的散列值上。
对于对象中某个关键域f(指equals方法涉及到的每个域),完成以下步骤
把某个非0的常数,比如说17 保持在int 类型的变量中
a.为该域计算int类型的散列码c
- 如果该域事boolean类型则计算f?1:0
- 如果该域是byte char short int 类型,则计算(int)f
- 如果该域是long类型,则计算(int)(f^(f>>>32))
- 如果该域是float类型,则计算Float.floatToIntBits(f)
- 如果该域是double类型,则计算Double.doubleToLongBits(f),然后按照步骤3 ,为得到的long类型计算散列值
- 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样为这个域递归的调用hashCode。如果需要更复杂的比较,则为这个域计算一个范式,然后针对这个范式调用hashCode。如果这个域为null则返回0(或者其它某个常数,但通常是0)
- 如果该域是一个数组,则要把每一个元素当作单独的域来处理。也就是说,递归的调用上述规则,对每个重要的元素计算散列码,然后根据步骤b的做法把这些散列吗组合起来。如果数组中的每个元素都很重要,可以利用发行版本1.5中增加的其中一个Arrays.hashCode
b. 按照下面的公式,把步骤1中计算得到的散列码c合并到result中
result = 31 * result +c
参考文献:effective Java 第二版 41 页。