由重写equals()就要重写hashCode()引发的思考

本文参考:JAVA为什么两个不同对象的hashCode有可能相同

1. equals()和hashCode()的关系

equals( ):

equals()在java中默认比较地址,是Object类中的方法,故所有对象子类都继承了此方法。但实际应用中常常重写此方法用于比较对象的内容。

hashCode():

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。public int hashCode()返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
既然hashcode为int类型,则最多有2^32个数值,也就自然可能发生冲突(哈希冲突)

二者关系:

一般来说,

  • 相同对象equals()返回true,hashCode()返回值相等
  • 不同对象equals()返回false,hashCode()返回值可能相等(哈希冲突)也可能不等

一句话总结,两对象equals时,hashCode一定相等;两对象hashCode相等时,不一定是相同对象。

3. 理解HashSet和HashMap

在讨论为何要同时重写equals()和hashCode()方法前,需要先对HashMap和HashSet有一定了解。

HashMap:

可以从HashMap的数据存取来理解HashMap。要将一个(key, value)数据存入HashMap大致要经过以下几步

  • 使用元素的key调用hashCode()方法获得哈希值,再经过某种哈希算法后获取在数组中的索引(下标)
  • 判断此下标位置中是否已存入过此元素
    • 若已有此元素,则对key对应的value进行更新
    • 若未存入过此元素,则放入(key, value)

可暂时将HashMap理解为一种数组加链表的数据结构,根据元素的key的hashCode确定数组下标,再将(key, value)存入此数组下标对应的链表。

HashSet:

这里先来看一下HashSet的构造方法源码:

public HashSet() {
 map = new HashMap<E,Object>();
}
// 构造器中new了一个HashMap。key使用了泛型,value使用Object。

再看下add()方法源码:

private static final Object PRESENT = new Object(); 
public boolean add(E e) { 
    return map.put(e, PRESENT)==null; 
} 
// PRESENT是一个Object类型的常量,用来当做map的value。也就是说,在HashSet中存储的元素都是HashMap中key,value全部使用Object。 

从上述代码可以看出,HashSet的底层其实就是HashMap,相当于只使用了HashMap的一列,也就是key部分来存储数据,value部分全部为一个Object类型的常量PRESENT

3. 为何要同时重写equals()和hashCode()

这里还是从哈希表存入数据的角度入手。当由hashCode获取到数组下标后,若当前位置没有元素,则直接放入;若有元素,则采用先比较哈希值再调用equals()的方法判断链表中是否有与待存储元素相同的元素(相同对象的哈希值相等,equals()返回true)。若没有,则将元素放入;若有,则更新元素。
由上述哈希表存入数据的原理可知,两对象只有当hashCode()和equals()返回值都相等时才会被判定为相同对象。所以只有保持equals()和hashCode()的一致性才能在更新哈希表时做到正常更新,而不是把相同的对象再次放入哈希表,造成内存浪费

4. 一句话总结

同时重写equals()和hashCode()可以避免由于相同元素不同hashCode导致的哈希表中重复元素的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值