“equals“ 和 ““==““ 的区别

“equals” 和 “”=="" 的区别

1. equals

1.1 作用

判断两个对象是否相等,返回值为boolean类型。

1.2 底层原理

在Object类种,equals的判断方法如下:

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

可以看到,Object 类种的 equals 方法其实就是 == 方法,两者相同。

那equals到底有何区别?

因为equals可以根据业务需要,实现你想要的比较方法。

通过equals(Object obj)括号内传入的对象,通过判断该对象的值、类型、是否为null等,返回与原对象是否相等,实现业务需求。

1.3 equals() 和 hashCode()的关系

1.3.1 不会创建“类对应的散列表”

”不会创建类对应的散列表“,指的是我们不会再HashSet,Hashtable,HashMap等这些本质是散列表的数据结构中,用到该类。例如,不会创建该类的HashSet集合。

在这种情况下,hashCode() 和 equals() 没有关系。

例如:

public class demo2 {
    public static void main(String[] args) {
        Persion p1 = new Persion("a", 1);
        Persion p2 = new Persion("a", 1);
        Persion p3 = new Persion("b", 1);

        System.out.println("p1.equals(p2)" + p1.equals(p2));
        System.out.println("p1.equals(p3)" + p1.equals(p3));
        System.out.println("p1的HashCode:" + p1.hashCode());
        System.out.println("p2的HashCode:" + p2.hashCode());
        System.out.println("p3的HashCode:" + p3.hashCode());
    }

    private static class Persion{
        String name;
        int sex;

        public Persion(String name,int sex){
            this.name = name;
            this.sex = sex;
        }

        @Override
        public boolean equals(Object obj){
            if(this==obj){
                return true;
            }
            if(this.getClass() != obj.getClass()){
                return false;
            }
            Persion persion = (Persion) obj;
            return name.equals(persion.name) && sex == persion.sex;
        }
    }
}

运行结果:

p1.equals(p2)true
p1.equals(p3)false
p1的HashCode:1950409828
p2的HashCode:1229416514
p3的HashCode:2016447921

结果分析:

p1,p2虽为两个不同的对象,但因为equals()没有比较对象的地址值,所以p1和p2相等,但hashcode()不等。

1.3.2 会创建“类对应的散列表”

会在HashSet、Hashtable、HashMap等这些本质是散列表的数据结构种,用到该类。在这种情况下,该类的 hashCode() 和 equals() 是有关系的。

如果两个对象相等(equals()两对象时返回true),那它们的hashCode()的值一定相同。

如果两个对象hashCode()相等,它们并不一定相等(哈希冲突)。

因此,在这种情况下判断两对象相等的,需要重写equals()和hashCode()方法。

(1)只重写equals()方法
    public static void main(String[] args) {
        Person p1 = new Person("aa",1);
        Person p2 = new Person("aa",1);
        Person p3 = new Person("bb",0);

        HashSet<Person> hashSet = new HashSet<>();
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);

        System.out.println("p1.equals(p2) : " + p1.equals(p2));
        System.out.println("p1: " + p1.hashCode() + ", p2: " + p2.hashCode());
        System.out.println(hashSet);
    }

    private static class Person{

        private String name;
        private int sex;

        public Person(String name,int sex){
            this.name = name;
            this.sex = sex;
        }

        @Override
        public String toString() {
            return name + "+" + sex;
        }

        @Override
        public boolean equals(Object obj){
            if(obj == null){
                return false;
            }else if(this == obj){
                return true;
            }else if(this.getClass() != obj.getClass()){
                return false;
            }

            Person person = (Person)obj;
            return name.equals(person.name) && sex==person.sex;
        }

运行结果:

p1.equals(p2) : true
p1: 1950409828, p2: 1229416514
[bb+0, aa+1, aa+1]

结果分析:

由此可知,只重写equals()方法,返回值为true时,hashCode()不一定相同。且set集合中有重复元素p1和p2。由此可知,p1和p2是不相等的。

(2)重写queals()和hashCode()方法:
public static void main(String[] args) {
        Person p1 = new Person("aa",1);
        Person p2 = new Person("aa",1);
        Person p3 = new Person("bb",0);
        Person p4 = new Person("AA",1);

        HashSet<Person> hashSet = new HashSet<>();
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        hashSet.add(p4);

        System.out.println("p1.equals(p2) : " + p1.equals(p2));
        System.out.println("p1: " + p1.hashCode() + ", p2: " + p2.hashCode());
        System.out.println("p1.equals(p4) : " + p1.equals(p4));
        System.out.println("p1: " + p1.hashCode() + ", p4: " + p4.hashCode());

        System.out.println(hashSet);
    }

    private static class Person{

        private String name;
        private int sex;

        public Person(String name,int sex){
            this.name = name;
            this.sex = sex;
        }

        @Override
        public String toString() {
            return name + "+" + sex;
        }

        /**
         * 重写hashCode算法,对name的值进行大写转换,然后计算hashCode
         */
        @Override
        public int hashCode(){
            int nameHash = name.toUpperCase().hashCode();
            return nameHash;
        }

        @Override
        public boolean equals(Object obj){
            if(obj == null){
                return false;
            }else if(this == obj){
                return true;
            }else if(this.getClass() != obj.getClass()){
                return false;
            }

            Person person = (Person)obj;
            return name.equals(person.name) && sex==person.sex;
        }
    }

运行结果:

p1.equals(p2) : true
p1: 2080, p2: 2080
p1.equals(p4) : false
p1: 2080, p4: 2080
[aa+1, bb+0, AA+1]

结果分析:

当重写 hashCode() 和 equals() 后,

比较p1和p2,hashCode相等,且equals()也相同,所以p1和p2相等;

比较p1和p4,hashCode相等,但equals()不相等,所以p1和p4不相等。

2. ==

2.1 作用

比较两个对象的堆内存地址,返回值为boolean类型。

2.2 基本数据类型比较

他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的,一个常量只会对应一个地址,所以当参数相同时,他们的引用都是指向同一地址的。因此基本数据类型和String常量是可以直接通过==来直接比较的。

2.3 包装类型比较

除了Float和Double之外,其它6种都是实现了常量池的,因此对于这些数据类型而言,一般也会直接通过==来判断是否相等。

但是有一个问题:

当数据超出数据类型存储范围时,如何比较?

例如:

Integer a = 127;
Integer b = 127;

Integer c = 128;
Integer d = 128;

System.out.println(a == b);
System.out.println(a == b);

输出结果是:

true、false

因为当超出数据类型范围时,会创建新的对象,此时,两对象的地址值不同,==的结果也就是false了。

总结

  1. 相同对象,无论何时调用hashCode(),返回值必须相等。
  2. 比较两对象时,若hashCode()相等时,两对象不一定相等,必须通过hashCode()和equals()方法同时判断,才能够确认两对象相同。
  3. 重写equals()函数,必须重写hashCode()函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值