Java中的hashCode() 和 equals()问题怎么解答?

一.equals() 的作用是什么?

equals() 的作用是 用来判断两个对象是否相等

equals() 定义在JDK的Object.java中。通过判断两个对象的地址是否相等(即是否是同一个对象)来区分它们是否相等。源码如下:

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

既然Object.java中定义了equals()方法,这就意味着所有的Java类都实现了equals()方法,所有的类都可以通过equals()去比较两个对象是否相等。但是我们知道使用默认的equals()方法,等价于==方法。因此,我们通常会重写equals()方法:若两个对象的内容相等,则equals()方法返回true;否则,返回fasle。

下面我们根据类是否覆盖equals()方法来区分:

  • 若某个类没有覆盖equals()方法,当通过equals()比较两个对象时,实际上是比较两个对象是不是同一个对象(比较的对象的内存地址)。这时,等价通过==去比较这两个对象。
  • 若某个类覆盖类的equals()方法,当通过equals()比较两个对象是否相等时,若两个对象的内容相等,则equals()方法返回true;否则,返回fasle。

下面我们举例来说明:

没有覆盖equals()方法的情况

public class Test{

    public static void main(String[] args) {

        Person p1 = new Person("张三", 25);
        Person p2 = new Person("张三", 25);
        System.out.printf(p1.equals(p2));
    }
}
private  class Person {
        int age;
        String name;

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

        public String toString() {
            return name + " - " +age;
        }
}

运行结果

false

结果分析

我们通过 p1.equals(p2) 来“比较p1和p2是否相等时”。实际上,调用的Object.java的equals()方法,即调用的 (p1==p2) 。它是比较“p1和p2是否是同一个对象”。
而由 p1 和 p2 的定义可知,它们虽然内容相同;但它们是两个不同的对象!因此,返回结果是false。

覆盖equals()方法的情况

我们把Person 类重新equal(),如下:

@Override
public boolean equals(Object obj){  
  if(obj == null){  
  return false;  
}  

//如果是同一个对象返回true,反之返回false  
if(this == obj){  
   return true;  
}  

//判断是否类型相同  
if(this.getClass() != obj.getClass()){  
   return false;  
}  

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

运行结果

true

结果分析

我们重写了Person的equals()函数:当两个Person对象的 name 和 age 都相等,则返回true。因此,运行结果返回true。

二.equals() 与 == 的区别是什么?

equals() : 它的作用也是判断两个对象是否相等。

  • 类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
  • 类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为这两个对象相等)。

对于==

  • 基本数据类型 :byte,short,char,int,long,float,double,boolean。则直接比较其存储的"值"是否相等。
  • 引用数据类型(String,Date):当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。

三.hashCode() 的作用是什么?

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。

hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。

虽然,每个Java类都包含hashCode() 函数。但是,仅仅当创建并某个“类的散列表时,该类的hashCode() 才有用(作用是:确定该类的每一个对象在散列表中

的位置;其它情况下(例如,创建类的单个对象,或者创建类的对象数组等等),类的hashCode() 没有作用。上面的散列表指的是:Java集合中本质是散列表

的类,如HashMap,Hashtable,HashSet。

综上所述:

hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

下面,我们以HashSet为例,来深入说明hashCode()的作用。

假设,HashSet中已经有1000个元素。当插入第1001个元素时,需要怎么处理?因为HashSet是Set集合,它允许有重复元素。将第1001个元素逐个的和前

面1000个元素进行比较”?显然,这个效率是相等低下的。散列表很好的解决了这个问题,它根据元素的散列码计算出元素在散列表中的位置,然后将元素插

入该位置即可。对于相同的元素,自然是只保存了一个。

由此可知,若两个元素相等,它们的散列码一定相等;但反过来确不一定。在散列表中

  • 如果两个对象相等,那么它们的hashCode()值一定要相同
  • 如果两个对象hashCode()相等,它们并不一定相等。

四.hashCode() 和 equals() 之间有什么联系?

1. 第一种 不会创建“类对应的散列表”

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

在这种情况下,该类的“hashCode() 和 equals() ”没有半毛钱关系的!

这种情况下,equals() 用来比较该类的两个对象是否相等。而hashCode() 则根本没有任何作用,所以,不用理会hashCode()。

下面,我们通过示例查看类的两个对象相等 以及 不等时hashCode()的取值。

public class Person {

    private String name;
    private String sex;

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

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

//    @Override
//    public int hashCode() {
//        return Objects.hash(name, sex);
//    }
}

 public static void main(String[] args) {
        Person person=new Person("张三","男");
        Person person1=new Person("张三","男");
        System.out.println("person.hashCode():"+person.hashCode()+"\t" +"person1.hashCode():"+person1.hashCode());
        System.out.println("equal:"+person.equals(person1));
    }

运行结果

person.hashCode():1639705018    
person1.hashCode():1627674070
equal:true

从结果也可以看出:personperson1相等的情况下,hashCode()也不一定相等。**

2. 第二种 会创建“类对应的散列表”

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

在这种情况下,该类的“hashCode() 和 equals() ”是有关系的:

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

如果两个对象hashCode()相等,它们并不一定相等。因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并

不一定能 得出键值对相等。

此外,在这种情况下。若要判断两个对象是否相等,除了要覆盖equals()之外,也要覆盖hashCode()函数。否则,equals()无效。

例如,创建Person类的HashSet集合,必须同时覆盖Person类的equals() 和 hashCode()方法。如果单单只是覆盖equals()方法。我们会发现,

equals()方法没有达到我们想要的效果。

代码实例:Person 如上没有重写hashcode()方法

public class Test {
    public static void main(String[] args) {
        Person person=new Person("张三","男");
        Person person1=new Person("张三","男");
        Person person2=new Person("张三","男");
        HashSet hashSet=new HashSet();
        hashSet.add(person);
        hashSet.add(person1);
        hashSet.add(person2);

        System.out.println("person.hashCode():"+person.hashCode());
        System.out.println("person1.hashCode():"+person1.hashCode());
        System.out.println("person2.hashCode():"+person1.hashCode());
        System.out.println("equal:"+person.equals(person1));


    }
}

运行结果

person.hashCode():1639705018
person1.hashCode():1627674070
person2.hashCode():1627674070
equal:true

结果分析

我们重写了Person的equals()。但是,很奇怪的发现:HashSet中仍然有重复元素:person 和 person1。为什么会出现这种情况呢?

这是因为虽然person 和person1的内容相等,但是它们的hashCode()不等;所以,HashSet在添加personperson1的时候,认为它们不相等。

下面,我们同时覆盖equals() 和 hashCode()方法。

public class Person {

    private String name;
    private String sex;

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, sex);
    }
}

运行结果

person.hashCode():24052527
person1.hashCode():24052527
person2.hashCode():24052527
equal:true

结果分析

这下,equals()生效了,HashSet中没有重复元素。

比较personperson1,我们发现:它们的hashCode()相等,通过equals()比较它们也返回true。所以,personperson1被视为相等。

小伙伴们有兴趣想了解更多相关学习资料请点赞收藏+评论转发+关注我之后

私信我,注意回复回复【000】点击此处链接即可获取更多免费资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾听铃的声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值