[java]深入理解equals和hashcode方法的区别和联系

"==”,equals方法,hashcode方法的区别和联系
1 equals() 的作用是什么

​ equal类是Object类的方法,Object是所有类的基类。

​ 在我们没有重写equals方法时,equals()的作用是比较两个对象地址是否相等,我们看看equal()的源码

       public boolean equals(Object obj) {
            return (this == obj);
        }

​ 我们可以对equals方法进行重写,来比较两个对象的内容是否相等。

代码1
    class Person1{
        int age;
        String name;
        Person1(){}
        Person1(int age,String name){
            this.age = age;
            this.name = name;
        }
    }
    public class Test4 {
        public static void main(String[] args) {
            Person1 p = new Person1();
            Person1 p1 = new Person1();
            System.out.println(p.equals(p1));
        }
    }

输出为false ,说明在没有重写equal方法时,比较的是内存地址

代码2
    class Person1{
        int age;
        String name;
        Person1(){}
        Person1(int age,String name){
            this.age = age;
            this.name = name;
        }
        @Override
        public boolean equals(Object obj) {
            if(obj == null) return false;
            if(this==obj) return true;
            Person1 p = (Person1)obj;
            if(this.age==p.age&&this.name.equals(p.name)) return true;
            return false;
        }
    }
    public class Test4 {
        public static void main(String[] args) {
            Person1 p = new Person1(12,"xiaowang");
            Person1 p1 = new Person1(12,"xiaowang");
            System.out.println(p.equals(p1));
        }
    }

输出为true,此时equal方法比较的是对象的内容

2 equals() 与 == 的区别是什么

​ "=="比较的是对象在内存中的地址

​ 重写后的equal方法比较的是对象的内容

3 hashCode() 的作用是什么
3.1 了解hashcode()的作用

​ hashcode()方法作用与散列表中,比如map,set集合。作用:通过对象的hashcode方法得到哈希码,哈希码决定对象在散列表存储的位置。

​ 我们知道散列表为key-value形式,通过输入key可以快速的检索到value,实现的方式就是用key的hashcode来检索的。计算key的hashcode得到了一个存储数据的索引位置,拿到对应索引位置的值就是value。

​ 简单的示意图。

在这里插入图片描述

3.2说到这里就浅谈一下HashMap的结构

在这里插入图片描述
当存放元素进去时,首先计算出key的hash码,如果hash码对应的位置没有元素,就把value存储到hash码对应的位置里。

如果有元素,这时候就产生了哈希冲突,HashMap是使用链地址法来解决的。什么是链地址法,就是计算出来的hash码对应的位置如果有值存在,比较首先key,如果key不相同,就把该元素链到hash值对应位置后。如果key相同,就对value进行覆盖。

当产生hash冲突的时候,对性能的影响是很大的。

**如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度依然为O(1),因为最新的Entry会插入链表头部,仅需简单改变引用链即可,而对于查找操作来讲,此时就需要遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。**所以重写hashcode是一门技术活,需要考虑尽量减少hash冲突

4 hashCode() 和 equals() 之间有什么联系?
4.1 如果该类没有用到散列表,这两个方法没有半毛钱关系!!!
Person1 p = new Person1(12,"xiaowang");
        Person1 p1 = new Person1(12,"xiaowang");
        System.out.println(p.equals(p1));
        System.out.println(p.hashCode());
        System.out.println(p1.hashCode());
        
   ------------------------
 true
460141958
1163157884
	

在只重写了equals方法,没有重写hashcode方法的情况下,对象相等,哈希码不相等。

4.2 如果该类有用到散列表,既要重写equals方法也要重写hashcode方法

其实,散列集合判断对象的方法就是先判断hashcode是否相等,如果相等再判断equals方法是否返回true,只有同时满足两个条件,最后才会被认为是相等的。

  • 如果两个对象相等,那么它们的hashCode()值一定相同
  • 如果两个对象hashCode()相等,它们并不一定相等
  • 这里的相等是指,通过equals()比较两个对象时返回true。

对map而言:map是基于key寻址的,首先通过key的hashcode方法计算出哈希值然后映射到一个存储地址,若已有对象则通过对象所在类的equals()依次比较两个对象是否相同,如果不相同,链在表后。如果相同,覆盖其值。

对set而言:set是map的一种特殊的实现,当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算次对象的哈希值,此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,若已有对象则通过对象所在类的equals()比较两个对象是否相同,相同则不能被添加。

4.3 两个对象值相同 (x.equals(y) == true) , 但却可有不同的 hashCode, 这句话对不对?

不对,如果两个对象值相同(x.equals(y)==true),hashcode必须相同

java 对于equal方法和hashcode是这样规定的:

(1)如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同

(2)如果两个对象的 hashCode 相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值