认识equals():
Object类中的equals;
public boolean equals(Object obj) {
return (this == obj);
}
当我们没有重写equals(),我们是调用父类object中的方法,比较的是对象的内存地址
重写equals后,
public class Student {
private int age;
private String name;
public Student() {
}
@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;
如果不相同,则比较对象的属性;对象的属性相同则返回true;
认识hashcode():
假如没有重写hashcode()通常返回的是对象内存地址取模后的哈希值
重写后:按一定的运算规则返回计算后的哈希值:通常情况下,对象相同,则返回相同的hash值
重写equals(),还要重写hashcode()的原因:
一:提高效率:考虑到 hashmap等哈希表结构中使用哈希码快速确定存储位置,方便高效;若发生hash冲突,再调用对象的equals()方法比较;
二:保持一致性:只重写equals()而没有重写hashcode();即使两个对象:x.equals(y)==true
也无法保证x.hashcode()==y.hashcode();在使用哈希表等数据结构时,无法找到正确对象从而导致一些意外;
因此既要重写equals(),又要重写hashcode();
举个例子:
Student类没有重写hashcode:
public class Student {
private int age;
private String name;
public Student() {
}
@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);
}
}
测试类:
public static void main(String[] args) {
Student s1 = new Student(18, "张三");
Student s2 = new Student(18, "张三");
HashMap<Student, Integer> hashMap = new HashMap<>();
hashMap.put(s1,100);
System.out.println("---------------");
System.out.println(s1.equals(s2));
System.out.println("--------------");
System.out.println("s1的哈希值:"+s1.hashCode());
System.out.println("s2的哈希值:"+s2.hashCode());
System.out.println(hashMap.get(s2));
}
结果为:
返回结果为:null
说明了即使两个对象equals()比较相同;也不能保证通过new Student(18,"张三")找到对应的value;因为s1,s2的哈希值不相同;
那么就不无法保证hashmap中元素的唯一性:因为相同的对象经过hash运算可以映射到不同槽位上,
那么就可以存储:(s1,100),s1(s1,100)
这不就是矛盾吗?
若我们重写了hashcode()方法:
@Override
public int hashCode() {
return Objects.hash(age, name);
}
输出结果为: