如果只重写equals方法不重写hashCode方法,就有可能导致a.equals(b) == true ,但是hashCode值不同,只重写了equals()方法的对象,在使用散列集合进行存储的时候就会出现问题。因为散列集合是通过hashCode值计算key的位置。如果存储两个完全相同的对象,但是有不同的hashCode,就会导致这两个对象存储在不同的位置。当我们想要根据这个对象获取数据的时候就会出现一个悖论,一个完全相同的对象,会存储在哈希表的两个位置。所以在开发过程中约定俗成的一条规则是“重写equals方法也需要要重写hashCode方法”。
可以参考:【Java】hashcode和equals如何使用?
如下代码是String中的equals()方法,当调用equals()方法去比较两个对象的时候,会比较两个东西,一个是通过==比较两个对象的内存地址是否相同,如果相同则返回true,否则继续去比较两个对象的值,如果这两个对象的值完全相同,则返回true;
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
equals()和hashCode的关系:
Java中任何对象都有一个native和hashCode方法,这个方法在散列集合中会被用到,比如HashMap这种集合类,当我们往里面添加元素的时候需要判断元素是否在这个集合里,直接使用equals比较的话效率太低,所以一般直接使用对象的hashCode值取模以后进行运算,如果这个Map里没有hashCode对应的值,那么可以直接把这个对象存进去,不用做任何比较,如果存在的话,就需要调用它的equals方法与新的元素进行比较。相同的话就直接覆盖,不同的话散列到其他地址, 这里面存在一个冲突解决的问题,这样来调用equals的方法次数就大大降低了,hashCode的值默认是jvm使用随机数生成的,两个不同的对象可能生成的hashCode值可能会相同。这种情况下,在哈希表里就会发生哈希冲突。通常会使用链表或线性探测的方法来解决这个冲突的问题。但是,如果两个完全相同的对象也就是内存地址指向同一个,那么他们的hashCode值一定是相同的。如果重写了equals方法没有写hashCode方法,就有可能导致a.equals(b)为true,但是hashCode的值不同,这样就导致不能和所有的集合类一起工作。