移动网站开发公司,wordpress 六亩填,做瑜伽网站,做vi 设计国外网站由于需要比较对象内容#xff0c;所以我们通常会重写 equals 方法#xff0c;但是重写 equals 方法的同时也需要重写 hashCode 方法#xff0c;有没有想过为什么#xff1f;
因为如果不这样做的话#xff0c;就会违反 hashCode 的通用约定#xff0c;从而导致该类无法结…由于需要比较对象内容所以我们通常会重写 equals 方法但是重写 equals 方法的同时也需要重写 hashCode 方法有没有想过为什么
因为如果不这样做的话就会违反 hashCode 的通用约定从而导致该类无法结合所有基于散列的集合一起正常工作这类集合包括 HashMap 和 HashSet。
这里的通用约定从 Object 类的 hashCode 方法的注释可以了解主要包括以下几个方面 在应用程序的执行期间只要对象的 equals 方法的比较操作所用到的信息没有被修改那么对同一个对象的多次调用hashCode 方法都必须始终返回同一个值。如果两个对象根据 equals 方法比较是相等的那么调用这两个对象中的 hashCode 方法都必须产生同样的整数结果。如果两个对象根据 equals 方法比较是不相等的那么调用者两个对象中的 hashCode 方法则不一定要求 hashCode 方法必须产生不同的结果。但是给不相等的对象产生不同的整数散列值是有可能提高散列表hash table的性能。 从理论上来说如果重写了 equals 方法而没有重写 hashCode 方法则违背了上述约定的第二条相等的对象必须拥有相等的散列值。
但是规则是大家默契的约定如果我们就喜欢不走寻常路在重写了 equals 方法后没有覆盖 hashCode 方法会产生什么后果吗
我们自定义一个 Student 类并且重写了 equals 方法但是我们没有重写 hashCode 方法那么当调用 Student 类的 hashCode 方法的时候默认就是调用超类 Object 的 hashCode 方法根据随机数返回的一个整型值。
public class Student {private String name;private String gender;public Student(String name, String gender) {this.name name;this.gender gender;}Overridepublic boolean equals(Object anObject) {if (this anObject) {return true;}if (anObject instanceof Student) {Student anotherStudent (Student) anObject;if (this.getName() anotherStudent.getName()|| this.getGender() anotherStudent.getGender())return true;}return false;}
}
我们创建两个对象并且设置属性值一样测试下结果
public static void main(String[] args) {Student student1 new Student(小明, male);Student student2 new Student(小明, male);System.out.println(equals结果 student1.equals(student2));System.out.println(对象1的散列值 student1.hashCode() 对象2的散列值 student2.hashCode());
}
得到的结果 equals结果true 对象1的散列值1058025095对象2的散列值665576141 我们重写了 equals 方法根据姓名和性别的属性来判断对象的内容是否相等但是 hashCode 由于是调用 Object 类的 hashCode 方法所以打印的是两个不相等的整型值。
如果这个对象我们用 HashMap 存储将对象作为 key熟知 HashMap 原理的同学应该知道HashMap 是由数组 链表的结构组成这样的结果就是因为它们 hashCode 不相等所以放在了数组的不同下标当我们根据 Key 去查询的时候结果就为 null。
public static void main(String[] args) {Student student1 new Student(小明, male);Student student2 new Student(小明, male);HashMapStudent, String hashMap new HashMap();hashMap.put(student1, 小明);String value hashMap.get(student2);System.out.println(value);
}
输出结果 null 得到的结果我们肯定不满意这里的 student1 和 student2 虽然内存地址不同但是它们的逻辑内容相同我们认为它们应该是相同的。
这里如果不好理解可以将 Student 类换成 String 类思考下String 类是我们常常作为 HashMap 的 Key 值使用的试想如果 String 类只重写了 equals 方法而没有重写 HashCode 方法这里将某个字符串 new String(s) 作为 Key 然后 put 一个值但是再根据 new String(s) 去 Get 的时候却得到 null 的结果这是难以让人接受的。
所以无论是理论的约定上还是实际编程中我们重写 equals 方法的同时总要重写 hashCode 方法请记住这点。
虽然 hashCode 方法被重写了但是如果我们想要获取原始的 Object 类中的哈希码我们可以通过 System.identityHashCode(Object a)来获取该方法返回默认的 Object 的 hashCode 方法值即使对象的 hashCode 方法被重写了也不影响。
public static native int identityHashCode(Object x);