文章目录
- 1、首先看看不重写情况下,equals方法和hashCode方法是干什么的
- 2、为什么需要重写equals方法
- 3、为什么要重写hashCode方法?
- 4 总结
- 5 快速生equals方法和hashCode方法
1、首先看看不重写情况下,equals方法和hashCode方法是干什么的
查看源码可以发现,equals()
方法和hashCode()
方法都是Objects
类中的方法,其中equals()
方法比较的是两个对象的地址是不是相同,hashCode()
方法是根据地址值生成一个整数数值。
这就表明,在不重写情况下,两个new出来的对象,不管他们内部的值是否相同,地址一般来说是不同的,所以equals和hashCode方法得到的结果是不一样的。
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
2、为什么需要重写equals方法
这个其实是根据我们的实际需求来的,而不是必须重写。
上面讲过,原生的equals
方法比较的是两个对象的地址是不是相等,也就是说,如果我们传入的是两个不同的对象,equals
方法得到的结果大部分情况下是不相等的。
但是我们在代码中运用到equals()
方法的场景是:我们有两个对象,想要比较两个对象的某些值,如果这些值相等,我们就认为这两个对象是相等的
。显然这个目的,原生的equals
不能满足,因此在这种需求的驱动下,我们需要重写equals
方法。
举个例子,学生类,包含名字和年龄字段,如果名字和年龄都相等,我们就认为是同一个对象。
Student student01 = new Student("Tom", 25);
Student student02 = new Student("Tom", 25);
System.out.println(student01.equals(student02));
上述代码的结果是false
,因为我们没有重写equals
,比较的是两个对象的地址,自然是不相等的
现在我们重写equals
方法:
class Student {
public String name;
public int age;
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);
}
}
重写之后返回true
3、为什么要重写hashCode方法?
先讲一下hashCode方法会用在什么地方?
一般是在HashMap
或者HashSet
这种集合中会用到,当我们在这类集合中查找对象的时候,首先会根据传入的key
和定义好的哈希函数得到一个哈希值,根据哈希值得到存放这个对象的数组的位置,再根据key的equals方法匹配相同key值获取对应的对象。
我们在写代码的时候,常常会通过HashSet
或者HashMap
给若干对象去重,这类集合在去重的时候会依次调用hashCode
方法和equals
方法,只有这两个函数返回的值都是相等的,这类集合才认为这两个对象重复了。
如果不重写hashCode
方法,集合在去重的时候,会首先调用原生的hashCode
方法,原生hashCode
方法是根据两个对象的地址生成的哈希值,所以去重会失败。
举个例子,这里定义了两个Tom
,目的是将重复的Tom
去掉,这里是没有重写hashCode
方法的,仅仅重写了equals
方法。
public class Solution01 {
public static void main(String[] args) {
Student student01 = new Student("Tom", 25);
Student student02 = new Student("Tom", 25);
Student student03 = new Student("Jack", 23);
Set<Student> studentSet = new HashSet<>();
studentSet.add(student01);
studentSet.add(student02);
studentSet.add(student03);
for (Student st : studentSet) {
System.out.println(st.name + " " + st.age);
}
}
}
class Student {
public String name;
public int age;
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);
}
}
结果显示,集合中仍然有3个对象。
现在我们重写hashCode
方法
public class Solution01 {
public static void main(String[] args) {
Student student01 = new Student("Tom", 25);
Student student02 = new Student("Tom", 25);
Student student03 = new Student("Jack", 23);
Set<Student> studentSet = new HashSet<>();
studentSet.add(student01);
studentSet.add(student02);
studentSet.add(student03);
for (Student st : studentSet) {
System.out.println(st.name + " " + st.age);
}
}
}
class Student {
public String name;
public int age;
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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
得到的结果如下:
4 总结
重写equals
方法是为了自定义判断两个对象是不是相等的标准
,一般来说我们要求:两个对象的属性都相同就认为是相等的,原生的equals
方法在判断两个对象是不是相等的标准是:两个对象的地址是不是相等。
重写hashCode
方法的目的是为了实现将对象放入哈希集合中去重的目的。因为哈希集合是先通过hashCode
方法,再通过equals
方法来判断是不是重复。如果第一步hashCode都不等,就直接认为这两个对象不相等了。
重写equals方法必须重写hashCode方法
其实是不准确的,需要根据需求来,如果你只想调用equals
方法比较两个对象是不是相等,那就没有必要重写hashcode方法,但是更多的场景是将对象放入hashSet
和hashMap
中,而我们一般认为两个对象的属性都相等就等价于这两个对象就相等了。所以再这种情况下,重写了equals
方法必须重写hashCode
方法。
5 快速生equals方法和hashCode方法
idea,右键,如下:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)