注明:本文完全来自Effective Java,以后方便查看。
理想情况下,一个散列函数应该把一个集合中不相等的实例均匀地分布到所有可能的散列值上。要想完全达到这种理想的情形是非常困难的,幸运的是,相对接近这种理想情形并不太困难。下面给出一种简单的“处方”。
1.把某个非零数值,比如17,保存在一个叫result得int类型的变量中。
2.对于对象中每一个关键域f,完成以下步骤:
a.为该域计算Int类型的散列码c:
①如果该域是boolean类型,则计算(f?0:1)
②如果该域是byte、char、short或者int类型,则计算(int)f
③如果该域是long类型,则计算(int)(f ^ (f>>>32))
④如果该域是float类型,则计算Float.floatToIntBits(f)
⑤如果该域是double类型,则计算Double.doubleToLongBits(f)
⑥如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样对这个域递归调用hashCode。如果要求一个更为复杂的比较,则为这个域计算一个“规范表示”,然后针对这个范式表示调用hashCode。如果这个域的值为null,则返回0(或者其他某个常熟,但习惯上使用0)。
⑦如果该域是一个数组,则把每一个元素当做单独的域来处理。也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤2.b中的做法把这些散列值组合起来。
b.按照下面的公式,把步骤a中计算得到的散列码c组合到result中:
result = 37*result + c;
3.返回result。
4.写完了hashCode方法之后,问自己“是否相等的实例具有相等的散列码”。如果不是的话,找出原因,并修正错误。
在散列码的计算过程中,把冗余域排除在外是可以接受的。
PhoneNumber的示例
public int hashCode() { int result = 17; result = 37 * result + areaCode; result = 37 * result + exchange; result = 37 * result + extension; return result; }