为什么要重写hashcode()和equels()

首先,int等基本数据类型的equels比较的是地址,和==是一样的,和Object类的原始equels方法一样
而String、Integer等包装类,Java则对equels方法进行了重写,先比较地址、再比较具体的值,对于Student这样的对象也是如此。

我们自己重写equels方法后,使得比较的是 具体内容 的值;

hashcode在重写前,hashcode方法得到的是通过 地址 算出的hash值
重写后比较的是 对象中具体内容 的hash值

hashmap、hashset等散列集合会用到hash值,再比较两个对象是否相等的时候,先调用hashcode方法,然后调用equels方法。

出现hashcode的原因是,只用equels进行比较,十分消耗性能。每一个要存入到hashmap中的值,都要和map中已有的对象进行地址和具体内容的
比较,而通过对象的地址得到的hash值,可以映射对象在map中的位置,只需要比较map中的这个位置有没有数据即可。

如果我们比较的对象没有在散列方面用到,只是重写equels,不重写hashcode是没有问题的

如果hashcode的值是不同的,此时不会继续往下调用equesl方法,即使是两个相同内容的对象,也会被判定为不同的对象,被存入到集合中。
如果hashcode的值是相同的,此时继续往下调用equesl方法,如果不重写,则先比较的是地址,此时同样也会被判定为不同的对象,被存入到集合中

相同的对象,hash值一定相同,
不同的对象,hash值可能相同。
hash碰撞:地址不同,但是得到了相同的hash值

我们的原则是,不管地址是否相同,只要内容相同就认为是同一个对象。
散列集合存储数据的重点在于对象的内容不同,而非地址。(重点!!)

如果只重写equels方法(有两种情况):
两个对象的hash值相同,继续调用equels方法来比较对象的内容,内容如果不同,则判定为不同对象,否则为相同对象。(毕竟hash值相同可能是因为两个对象地址相同,也可能是发生了hash碰撞)

两个对象的hash值不相同,直接存入,这会导致hashmap等散列集合在比较对象的时候
,单纯的因为地址不同(此时不会继续调用equels方法),而将内容相同的两个对象同时存入,导致错误。

如果只重写hashcode方法(有两种情况)
两个对象的hash值相同,继续调用原始equels方法,原始equels方法先比较的是地址,如果实际上是两个不同地址、相同内容的对象,只是hash碰撞导致hash值相同
,在调用equels方法后,最终判定这是两个不同的对象,从而存入散列集合中,导致错误。

两个对象的hash值不相同,直接存入,此为正确情况。

两个方法都重写之后,hash值比较的是对象内容的hash值,equels比较的是内容,
前者保证了两个不同地址、相同内容的对象,不在因为单纯的地址不同而被存入,
后者则保证了hash值相同时(无论是否由hash碰撞引起),可以从内容上正确的区分是否为两个相同的对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值