1.在应用程序执行期间,只要对象的 equals 方法的比较操作所用到的信息没有被修改,那么对这同一个对象多次调用,hashCode 方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执
行过程中,每次执行所返回的整数可以不一致。
2.如果两个对象根据 equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的 hashCode 方法都必须产生同样的整数结果。
3.如果两个对象根据 equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的 hashCode 方法,则不一定要产生不同的整数结果。但是程序员应该知道,给不相等的对象产生截然
不同的整数结果,有可能提高散列表的性能。如果类没有覆盖 hashCode 方法,那么 Object 中缺省的 hashCode 实现是基于对象地址的,就像equals 在 Object 中的缺省实现一样。如果我们覆盖了equals 方法,
那么对象之间的相等性比较将会产生新的逻辑,而此逻辑也应该同样适用于 hashCode 中散列码的计算,既参与 equals 比较的域字段也同样要参与 hashCode 散列码的计算。
1 package com.twoslow.cha3;
2
3 public final class PhoneNumber {
4
5 private final short areaCode;
6 private final short prefix;
7 private final short lineNumber;
8
9 public PhoneNumber(int areaCode, int prefix, int lineNumber) {
10 this.areaCode = (short) areaCode;
11 this.prefix = (short) prefix;
12 this.lineNumber = (short) lineNumber;
13 }
14
15 @Override
16 public boolean equals(Object o) {
17 if(o == this)
18 return true ;
19
20 if(!(o instanceof PhoneNumber))
21 return false ;
22
23 PhoneNumber pn = (PhoneNumber) o ;
24 return pn.areaCode == areaCode
25 && pn.prefix == prefix && pn.lineNumber == lineNumber ;
26 }
27
28
29 /*
30 * 如果不覆盖hashCode,导致两个相等的实例具有不相等的散列码。
31 */
32 @Override
33 public int hashCode() {
34 int result = 17;
35 result = 31 * result + areaCode;
36 result = 31 * result + prefix;
37 result = 31 * result + lineNumber;
38 return result;
39 }
40 }
1 Map<PhoneNumber, String> map = new HashMap<PhoneNumber, String>() ;
2
3 PhoneNumber pn1 = new PhoneNumber(1, 2, 3) ;
4 map.put(pn1, "cjh") ;
5 PhoneNumber pn2 = new PhoneNumber(1, 2, 3) ;
6 //如果不覆盖hashCode,map.get(pn2)为null
7 System.out.println(map.get(pn2));
覆盖hashCode的一个简单的解决办法:
1.final int result = 17 ;或者某个非0的常数。
2.为该域计算int类型的散列吗c:
a.如果该域是boolean类型,则计算(f?1:0).
b.如果该域是byte、char、short、或者int类型,则计算(int)f.
c.如果该域是long类型,则计算(int)(f^(f>>>32))
d.如果该域是float类型,则计算Float.floatToIntBits(f).
e.如果该域是double类型,则计算Double.doubleToLongBits(f),然后按照步骤c,为得到的long类型值计算散列值。
f.如果该域是一个对象引用,并且该类的equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递归地调用hashCode。
h.如果该域是一个数组,则要把每一个元素当做单独的域来处理。如果每个元素都很重要,可以使用Arrays.hashCode()方法。
3.按照下面的公式,把步骤2中计算得到的散列码c合并到result中:result = 31 * result + c ;
4.返回result。
5.验证是否正确。