为什么要重写hashCode方法?
我们应该先了解java判断两个对象是否相等的规则。
在java的集合中,判断两个对象是否相等的规则是:
首先,判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等
如果相等,则判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等
我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率
如何重写hashCode方法呢?
1、把某个素数,比如说17,保存在一个叫result 的int 类型的变量值中。
2、对于对象中的每一个关键域f (指equals 方法中考虑的每一个域),完成以下步骤:
- 为该域计算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) 得到一个long 类型的值,然后按照步骤2.a.iii 对该long 类型计算散列值;
- 如果该域是一个对象引用,并且该类的equals 方法通过递归调用equals 的方式来比较这个域,则同样对这个域递归调用hashCode 方法;如果要求一个更为复杂的比较,则为这个域计算一个“规范表示”,然后针对这个规范表示调用hashCode。如果这个域的值为null,则返回0;
- 如果该域是一个数组,则把每一个元素当做单独的域来处理。然后根据步骤2.b 中的做法把这些散列值组合起来。
- 按照下面的公式,把步骤a 中计算得到的散列码c 组合到result 中:
result = 37 * result + c;
3、返回result 值。
注:根据实践经验,在对ASCII 串的散列函数中,31 和37 是很好的散列因子。
示例代码:
public class Test {
private String s = null;
private int id = 0;
.
.
.
public int hashCode() {
int result = 17;
result = 37 * result + s.hashCode();
result = 37 * result + id;
return result;
}
}
|