关于Object与String类中hashcode()的区别,以及equals()与toString(),hashcode()联系

11 篇文章 0 订阅

这个文章的标题是我由别的问题而引发的疑问:

1. 为何子类一般都要重写equals()这个方法

2. 为何重写equals()方法时需要重写hashcode()方法, 而hashcode()方法的作用又是如何,hash值是怎么计算的

    然后通过看源码发现Object类与String类中都有hashcode()方法,接下来为大家一一梳理这其中equals()与toString(),hashcode()的联系以及两个类中hashcode()方法的区别

一、hashcode()方法的由来和作用

     首先我们需要明白,hashcode()方法是用于哈希查找,可以减少在查找中使用equals()的次数,例如在JAVA的Set是不可加入重复元素的,加入Set的元素必须定义equals()方法以确保对象的唯一性,当元素多时为了避免过多使用equals()方法,便采用了哈希表的原理。当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了;不相同,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。所以这里存在一个冲突解决的问题(很少出现)。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。 
    所以,Java对于eqauls()方法和hashCode()方法是这样规定的: 
           1、如果两个对象相等,那么它们的hashCode值一定要相等; 
           2、如果两个对象的hashCode相等,它们并不一定相等。 

上面说的对象相等指的是用eqauls()方法比较。

二、为什么重写equals()方法时要重写hashcode()方法

    Object 类是所有类的父类,其 equals 方法比较的是两个对象的引用指向的地址,hashcode 是一个本地方法,返回的是对象地址值。他们都是通过比较地址来比较对象是否相等的,所以可以这样理解:重写了 equals 方法,判断对象相等的业务逻辑就变了,类的设计者不希望通过比较内存地址来比较两个对象是否相等,而 hashcode 方法继续按照地址去比较也没有什么意义了,索性就跟着一起变吧。

    为了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的,但hashcode却是不相同的。

    HashSet集合判断两个元素相等的标准是:两个对象通过equals()方法比较相等,并且两个对象的HashCode()方法返回值也相等。如果两个元素通过equals()方法比较返回true,但是它们的hashCode()方法返回值不同,HashSet会把它们存储在不同的位置,依然可以添加成功。若重写equals()方法时没有重写hashcode()方法则会破坏了HashSet的元素不可重复的特性。所以重写 hashcode 方法是为了让我们能够正常使用 HashSet 等集合类,因为 HashMap 判断对象是否相等既要比较 hashcode 又要使用 equals 比较。而这样的实现是为了提高 HashSet 的效率。

    其次,根据Object类中关于hashCode()方法的注释中翻译一下,hashCode()和equals()保持一致,如果equals方法返回true,那么两个对象的hasCode()返回值必须一样。如果equals方法返回false,hashcode可以不一样,但是这样不利于哈希表的性能,一般我们也不要这样做。重写equals()方法就必须重写hashCode()方法的原因也就显而易见了。

    

 

 

 

 

参考文章:

    https://github.com/francistao/LearningNotes/blob/master/Part2/JavaSE/Java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md

       https://blog.csdn.net/u013679744/article/details/57074669

       https://blog.csdn.net/u014756517/article/details/51935157

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值