转载

hashCode为什么存在?




这篇文章我想讲讲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为什么存在?

Java
  • 作者:CodeC.C(联系作者)
  • 发表时间:2020-09-16 21:14:22
  • 评论  null  条