hashCode()与 equals() 之间的关系

一、介绍

​ 简单介绍与一下 hashCode()equals()

1. equals()

equals() 方法用于比较两个对象是否相等,它与 == 相等比较符有着本质的不同。
区别参考:== 和 equals 的区别

2. hashCode()

w3c说明:
  hashCode() 方法用于返回字符串的哈希码
  字符串对象的哈希码根据以下公式计算:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。空字符串的哈希值为 0。

以下摘自: 深入探究Java中hashCode()和equals()的关系 - 简介 - hashCode()

暂且不谈冲突, 就因为相同的输入能够产生相同的输出这点而言,是及其宝贵的。它使得系统只需要通过简单的运算,在时间复杂度O(1)的情况下就能得出数据的映射关系,根据这种特性,散列表应运而生。

一种主流的散列表实现是:用数组作为哈希函数的输出域,输入值经过哈希函数计算后得到哈希值。然后根据哈希值,在数组种找到对应的存储单元。当发生冲突时,对应的存储单元以链表的形式保存冲突的数据。

二、为什么重写 equals 时必须重写 hashCode 方法?

如果两个对象相等,则 hashcode 一定也是相同的。两个对象相等,对两个对象分别调用 equals 方法都返回 true。但是,两个对象有相同的 hashcode 值,它们也不一定是相等的 。因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。

hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

摘自: hashCode()与 equals()

这里贴一个之前看到的

String th = "通话";
String zd = "重地";
System.out.println(th.hashCode());// 1179395
System.out.println(zd.hashCode());// 1179395

三、个人总结

以上内容解释了为什么重写 方法就必须重写 hashCode 方法。这里个人给一个写实体类中为什么要重写equal 方法和 hashCode 方法。都知道像 hashSet , hashMap 之类的存储是以哈希值来散列的方式存值。 如果实体不重写 hashCode 方法,那么用 这些集合存储时会出现重复的对象,就因为其哈希值不同。这里用 Set 集合测试 ,底层是 hashMap . 这篇文章末有源码分析带注释 深入探究Java中hashCode()和equals()的关系

个人代码:

Student stu1 = new Student("zhangsan", 18);
Student stu2 = new Student("zhangsan", 18);
// 重写 equals()前
// eq  false 
// 重写后
// eq  true
System.out.println(stu1.equals(stu2));

// 重写 hashCode() 前
// Student{name='zhangsan', age=18}
// Student{name='zhangsan', age=18}
// 重写后
// Student{name='zhangsan', age=18}
Set<Student> set = new HashSet<>();
set.add(stu1);
set.add(stu2);
for (Student student : set) {
   System.out.println(student);
}
// 

Student 类

class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
        //System.identityHashCode() 此方法用于查内存地址
//        System.out.println(System.identityHashCode(this));
//        System.out.println(System.identityHashCode(o));
//        return this == o;
    }

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

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

四、参考

hashCode()与 equals()
深入探究Java中hashCode()和equals()的关系

posted @ 2020-11-15 16:18  东郊  阅读(714)  评论(0编辑  收藏  举报