不这样就违反Object.hashCode的通用约定,导致该类无法结合所有基于散列的集合(HashMap、HashSet和Hashtable)一起正常运作。
hashcode方法就是返回对象的哈希码值
一、约定内容
1、同一对象调用多次,hashCode方法都必须返回同一整数。
同一应用程序的多次执行过程中,每次执行返回的整数可以不一致。
2、equals比较相等,hashCode方法都必须产生同样的整数结果。
3、equals方法比较不相等,hashCode方法不一定是不同的整数结果。
不相等的对象产生不同的整数结果,有可能提高散列表(hash table)的性能。(entity只根据id比较是否相等,在没实例化之前,没有id数值,equals返回false,hashCode值相等。)
运行下面代码:
Map map =newHashMap();
map.put(newPhoneNumber(707, 867, 5309), "Jenny");
System.out.println(map.get(newPhoneNumber(707, 867, 5309)));
期望返回Jenny,然而它返回的是null。
违反了hashCode的约定,PhoneNumber没有覆盖hashCode方法,导致两个相等的实例拥有不相等的散列码,put方法把电话号码对象放在一个散列桶中,get方法从另外一个散列桶中查找这个电话号码的所有者,显然是无法找到的。
二、设置好的散列函数
通常倾向于“为不相等的对象产生不同的散列码”。
理想情况下,散列函数应该把集合中不相等的实例均匀地分布到所有可能的散列值上。实际上达到困难的。
设置办法(上面解决办法):
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),然后再按照long类型处理
对于对象引用,并且该类的equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递归地调用hashcode
对于数组,则把每一个元素当作单独的域来处理。
b. 将获取到的c合并:result = 31 * reuslt + c;
c. 返回result
ps:如果类不可变,且计算散列码的开销大,把散列码缓存在对象内部,而不是每次请求的时候都重新计算散列码。
https://www.jianshu.com/p/40ee40f155aa
https://www.cnblogs.com/13jhzeng/p/5644368.html