结论:因为hashcode方法需要在散列集合中使用,如果不重写hashcode方法,当前类就不能和其他集合类协同工作。
在我们需要将当前类的对象(待添加元素)添加到散列集合中时,如果集合中没有这个hashcode值,说明待添加元素在这个集合中不存在,那么我们就可以直接将这个元素添加到集合中;如果集合中存在这个hashcode值,就需要调用它的equals方法与新的元素进行比较,如果相同,新元素直接覆盖旧元素,如果不相同,新元素就散列到集合的其他位置。(减少equals方法的调用,提高效率,因为equals比较的是对象内部信息,而hashcode比较的是一个数)
举个例子:假设x.equals(y)==true,如果没有重写equals方法,说明当前比较的是两个对象的内存地址,内存地址相同,那么hashcode值一定相同;如果重写了equals方法,没有重写hashcode方法,就可能导致hashcode值不相同,就会导致当前对象的类无法和其他集合类一起工作。
// 示例代码,只重写了equals方法,没有重写hashcode方法
public class Student {
private Integer id;
private String name;
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null || obj.getClass() != getClass()){
return false;
}
Student student = (Student) obj;
return Objects.equals(id, student.id) && Objects.equals(name, student.name);
}
}
测试方法
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student(11, "zhangsan");
Student s2 = new Student(11, "zhangsan");
System.out.println(s1.equals(s2));// true,重写了equals方法,比较的是对象内部信息
System.out.println(s1.hashCode() == s2.hashCode());// false,没有重写hashCode方法
Set<Student> set = new HashSet<>();
set.add(s1);
set.add(s2);
System.out.println(set.size());// 2,因为hashCode不同,所以程序认为这是两个不同的对象
}
}
此时就会出现两个完全相同的对象,存储在了哈希表中的不同位置的问题。
而当重写equals方法,同时重写hashcode方法后(在上面Student类代码中添加以下代码)
@Override
public int hashCode() {
return Objects.hash(id, name);
}
再次执行测试代码
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student(11, "zhangsan");
Student s2 = new Student(11, "zhangsan");
System.out.println(s1.equals(s2));// true,重写了equals方法
System.out.println(s1.hashCode() == s2.hashCode());// true,重写了hashCode方法
Set<Student> set = new HashSet<>();
set.add(s1);
set.add(s2);
System.out.println(set.size());// 1,在添加s2时,先用hashcode比较,后用equals比较,发现两个元素是同一个,所以第二次add操作不执行
}
}
注意:
1. 如果两个对象使用equals方法返回true,那么他们两个对象的hashcode值肯定相等(前提:需要重写hashcode方法,否则就会出现equals相等,hashcode不相等的情况)
2. 而如果hashcode值相等,equals方法不一定返回true
发生哈希冲突时的解决办法,参考链接:解决哈希冲突(四种方法)_哈希冲突的解决方法_君诀的博客-优快云博客
- 开放地址法(线性探测法,平方探测法)
- 链地址法