equal()和hashcode()方法简析

简介: 由于equal()和hashcode()是object中的方法,所以每个类中都有这两个方法,但在实际应用中往往需要重写这两个方法。 重写equal()和hashcode()方法假设场景:java中的Set集合的特性之一是会去除相同的元素。

由于equal()和hashcode()是object中的方法,所以每个类中都有这两个方法,但在实际应用中往往需要重写这两个方法。

重写equal()和hashcode()方法
假设场景:java中的Set集合的特性之一是会去除相同的元素。假设在Set集合中存学生对象,同一个人只能在Set集合中存一次,判断一个学生是否是同一个人的依据为:姓名相同,年龄相同,即为同一人。
编写一个Student类:

public class Student {
    private String name;
    private Integer age;

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

       //todo 添加get/set 方法

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

编写一个测试类:

public class SetTest {

    /**
     * 假设一场景:判断一个学生是否是同一个人的依据为:姓名相同,年龄相同,即为同一人
     * @param args
     */
    public static void main(String [] args){

        Set set = new HashSet();
        set.add(new Student("xiaoming",22));
        set.add(new Student("liangliang",24));
        set.add(new Student("xiaoming",22));
        set.add(new Student("daming",23));
        set.add(new Student("xiaoming",23));

        for (Iterator it =set.iterator();it.hasNext();){
            System.out.println(it.next());
        }
    }
}

测试结果:
image
显然,结果中出现两个xiaoming,年龄都为22,应该判断为一个人。出现这个结果是因为new出的每一个对象,哈希值是不同的, 想要实现预定的需求,必然要重写equal方法和hashcode方法。
在student类中重写这两个方法:

@Override
    public int hashCode() {
        return this.name.hashCode()+age * 31;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(!(this instanceof Student)){
            throw  new ClassCastException("类型不一样");
        }
        Student stu = (Student) obj; 
        return this.age == stu.age && this.name == stu.name;
    }

重写equal方法和hashcode方法有多种,可以根据自己的实际需求来指定合适的重写方法。
测试结果:
image

实现所需要的结果。

思考:为什么要重写equal和hashcode方法,这两个方法的调用机制是什么?

java中引入hashcode的方法主要就是为了查找方便,如果是一个数组去实现,想要找到其中一个值,就需要一个一个去比较,在数据量很大的情况下,性能会特别差,用hashcode方法可以快速找到存储的位置。那是否只重写hashcode()方法就可以呢?答案是否定的。只覆写hashcode 的方法,还是得不到预期的结果,因为同名同年龄得到的哈希值是一样的,当hash值一样时,就会去比较equal方法,此时调用的是object中的equal()方法,比较的是地址,都是新new出对象,地址不一样,所以equal返回为false,判断出两个学生不是同一人,所以要同时覆写equal方法。

这两个调用机制是什么呢,是先调用equal()方法,还是先调用hashcode()方法,接下来做个小实验,在这两个方法中分别打印出调用的对象:


  @Override
    public int hashCode() {
        System.out.println(this.getName()+"调用hashcode方法:"+this.name.hashCode()+age * 31);
        return this.name.hashCode()+age * 31;
      //  return age ;
    }
    @Override
    public boolean equals(Object obj) {

        if(this == obj)
            return true;
        if(!(this instanceof Student)){
            throw  new ClassCastException("类型不一样");
        }
        Student stu = (Student) obj;
        System.out.println(this.getName()+"调用equal方法" +stu.getName());
        //此equal()方法为String中的方法
        return this.age == stu.age &&  this.name.equals( stu.name);
    }

测试结果:
image

所以,在比较是否为同一个人时,首先会调用它的hashcode()方法,只有当hashcode()值一样是才回去调用equal()方法。第二个xiaoming是先调用hashcode()方法,发现和第一个xiaoming的哈希值是星等的,才再去比较equal()方法。这种机制会减少很多比较,提升效率。

如果两个对象的hashcode值不同,则必是两个不同的对象;但,两个不同的对象所产生的hashcode值是可能一样的,称为哈希碰撞。

最后欣赏下IDEA自动生成的equal()和hashcode()方法:


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

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
目录
相关文章
|
6月前
|
存储 Java
【面试题精讲】为什么重写equals时必须重写hashCode方法?
【面试题精讲】为什么重写equals时必须重写hashCode方法?
|
4月前
|
存储 算法 Java
史上最全的Java容器集合之equals 和 hashCode
史上最全的Java容器集合之equals 和 hashCode
37 0
|
7月前
|
算法 Java 索引
equals方法和hashCode方法之间的那些事(1.1)
equals方法和hashCode方法之间的那些事(1.1)
|
8月前
|
存储 Java
引以为戒:避免在Set中使用未重写equals和hashCode的引用对象进行去重
在日常的Java开发中,我们经常会使用Set集合来实现去重操作,确保集合中不含有重复的元素。然而,如果使用未重写equals()和hashCode()方法的引用对象进行去重,可能会导致意外的行为,最近了在项目中就遇到了这个情况,让我们深入探讨这个问题,并引以为戒,确保正确实现去重操作。
45 0
引以为戒:避免在Set中使用未重写equals和hashCode的引用对象进行去重
|
10月前
|
Java 索引
【JAVA基础】equal和hashcode的区别
【JAVA基础】equal和hashcode的区别
“==“和equals方法有什么区别(面试)
" == " 比较的是值 " == " 如果比较的是基本数据类型,比较的则是变量值 " == " 如果比较的为引用数据类型,比较的则是地址值
71 0
hashCode和equal方法
hashCode和equal方法
|
存储 算法 Java
Java 细品 重写equals方法 和 hashcode 方法
Java 细品 重写equals方法 和 hashcode 方法
235 0
Java 细品 重写equals方法 和 hashcode 方法
|
存储 索引
自定义对象作为map哈希表的 键key 时【为啥建议要重写hashCode( )、equals( ) 方法】
自定义对象作为map哈希表的 键key 时【为啥建议要重写hashCode( )、equals( ) 方法】
146 0
自定义对象作为map哈希表的 键key 时【为啥建议要重写hashCode( )、equals( ) 方法】
|
存储 Java
每天一个知识点(五)两个对象的 hashCode()相同,则 equals()也一定为 true吗?
两个对象的 hashCode()相同,则 equals()也一定为 true吗?

热门文章

最新文章