这篇文章我想讲讲equals()和hashCode()的区别,这两个方法是Object类使用最频繁的两个方法,也是面试官考察基础时比较喜欢提问的两个方法。 首先,话不多说,一句话总结:
equals()用于判断两个对象是否相等,这是大家公认的。 hashCode()被设计是用来使得哈希容器能高效的工作。
为什么这么说?在Java中,有一些哈希容器,比如Hashtable,HashMap等等。当我们调用这些容器的诸如get(Object obj)方法时,容器的内部肯定需要判断一下当前obj对象在容器中是否存在,然后再进行后续的操作。一般来说,判断是够存在,肯定是要将obj对象和容器中的每个元素一一进行比较,要使用equals()才是正确的。
但是如果哈希容器中的元素有很多的时候,使用equals()必然会很慢。这个时候我们想到一种替代方案就是hashCode():当我们调用哈希容器的get(Object obj)方法时,它会首先利用查看当前容器中是否存在有相同哈希值的对象,如果不存在,那么直接返回null;如果存在,再调用当前对象的equals()方法比较一下看哈希处的对象是否和要查找的对象相同;如果不相同,那么返回null。如果相同,则返回该哈希处的对象。
hashCode()返回一个int类型,两个int类型比较起来要快很多。所以我在文章开头说,hashCode()被设计用来使得哈希容器能高效的工作。也只有在哈希容器中,才使用hashCode()来比较对象是否相等,但要注意这种比较是一种弱的比较,还要利用equals()方法最终确认。
我们把hashCode()相等看成是两个对象相等的必要非充分条件,把equals()相等看成是两个对象相等的充要条件。
因此,在自定义一个类的时候,我们必须要同时重写equals()和hashCode(),并且必须保证: 其一:如果两个对象的equals()相等,那么他们的hashCode()必定相等。 其二:如果两个对象的hashCode()不相等,那么他们的equals()必定不等。
import java.util.HashMap;
public class Demo {
public static void main(String[] args) throws Exception{
Person person=new Person("xyz",22);
HashMap<Person,Integer> hashMap=new HashMap<Person,Integer>();
hashMap.put(person, 1);
System.out.println(hashMap.get(new Person("xyz",22)));
}
}
class Person {
private String name;
private int age;
public Person(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;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
// @Override
// public int hashCode() {
// int result = name != null ? name.hashCode() : 0;
// result = 31 * result + age;
// return result;
// }
}
上面的代码注释掉hashCode()前后的运行结果不同,当注释掉hashCode()的时候,person和后来新建的Person虽然equals是同一对象,但HashMap容器内部在首先比较hashCode()的时候会认为他们是不同元素,所以返回的值不同。
牢记:
重写equals()方法时候一定要重写hashCode()方法。 hashCode()相等是两个对象相等的必要非充分条件。 equals()相等是两个对象相等的充要条件。
import java.util.HashMap;
public class Demo {
public static void main(String[] args) throws Exception{
Person person=new Person("xyz",22);
HashMap<Person,Integer> hashMap=new HashMap<Person,Integer>();
hashMap.put(person, 1);
System.out.println(hashMap.get(new Person("xyz",22)));
}
}
class Person {
private String name;
private int age;
public Person(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;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
// @Override
// public int hashCode() {
// int result = name != null ? name.hashCode() : 0;
// result = 31 * result + age;
// return result;
// }
}
转自知乎义臻,原文地址:hashCode为什么存在?
评论 null 条