==、equals、hashcode比较与重写

本文深入解析Java中==和equals的区别,探讨它们在值类型和引用类型中的应用,以及equals与hashCode的关系,通过实例说明如何正确重写equals和hashCode方法。

==和equals的区别:

值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。

==操作比较的是两个变量的值是否相等,对于引用型变量表示的是栈中的内容是否相同。equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

总结:==比较的是2个对象的内存地址,而equals需要去比较的是2个对象的内容;

补充

  1. 八种基本数据类型(整数:byte,short,int,long,字符:char,小数:double,float,布尔:boolean)没有equals方法,只有其对应的封装类(如:Integer,Character,Double)才能调用equals。
  2. 未重写equals的类,继承的是Object的equals方法,源码中是
    public boolean equals(Object obj) {
            return (this == obj);
        }

    与 ’==‘是等价的,所以有下面的一个示例。

        String a="string";
        String b="string";
        String c=new String("string");
        String d=new String("string");

        /*
            a==b:::::::::::true
            a==c:::::::::::false
            a.equals(c):::::::::::true
            c==d:::::::::::false
            c.equals(d):::::::::::true
        * */
      
         class thisIsClass {
            private Integer i;
            thisIsClass(int i){
                this.i=i;
            }

            @Override
            public boolean equals(Object object){
                if(object instanceof thisIsClass){
                    thisIsClass c= (thisIsClass) object;
                    return i.equals(c.i);
                }
                return false;
            }
        }
        thisIsClass thisIsClass1=new thisIsClass(1);
        thisIsClass thisIsClass2=new thisIsClass(1);
/**
         * thisIsClass1==thisIsClass2:::::::::::false
         * thisIsClass1.equals(thisIsClass2):::::::::::true                 未重写thisIsClass的equals时,这个方法返回为false
         */

类型比较参考:https://www.cnblogs.com/pop822/p/6215040.html

equals和hashCode之间的关系

1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。

2、如果两个对象的hashCode相同,它们并不一定相同。

不同对象中重写的equal()里,一般比较的全面、复杂,这样效率就比较低;而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高,但两个不同对象的hashCode可能相同,所以hashCode的比较不是绝对可靠的。

为保证对比大量数据的效率和绝对正确性,对比时,首先用hashCode()去对比,如果hashCode()不一样,返回这两个对象不相等的结果(也就是不必再用equal()去再对比了);如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则返回这两个对象相同的结果。

参考:https://www.cnblogs.com/keyi/p/7119825.html

为什么重写equals就要重写hashCode

如果重写了equals,比如说是基于对象的内容实现的,而hashCode未重写,那么很可能某两个对象明明是“相等”,而hashCode却不一样。

问题出现:当把两个对象作为hashMap、hasoTable或hashSet的key时,map中就会存在两个“相等”的key

重写hashcode注意事项:

1. 如果hashcode方法用到了对象类型,那么该对象类型也必须要重写hashcode方法

2. 为了避免相同的对象计算出不同的hash值,hashcode中应计算所有出现在equals中的字段,且不能加入其他字段

3. 在JVM中,n*31会被优化(n<<5)-n,移位和减法的操作效率比乘法的操作效率高很多

4. 谷歌的架构师指出,需初始化一个整形变量,为此变量赋予一个非零的常数值,比如int hash= 17;

eg:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && gender == person.gender && Objects.equals(name,person.name);
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 31 + getName()!=null?getName().hashCode():0;
        hash = hash * 31 + getAge()!=null?getAge():0;
        hash = hash * 31 + getGender()!=null?getGender().hashCode():0;
        return hash;
    }

5. 对于类的hashCode、get、set等方法,可以使用依赖lombok的注解来完成

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值