【Java基础】hashCode()方法和equals()方法的作用

  首先需要明确hashCode()equals()Object类中定义的方法。所以Java中任何一个对象都具有这两种方法。这里有两个重要的规范:
  1.若重写equals(Object obj)方法,有必要重写hashCode()方法。因为如果两个对象相同,那么他们的hashCode一定相等。
  2.如果equals(Object obj)返回false,即两个对象“不相等”,但并不表明这个两个对象调用hashCode()方法一定返回两个不同的值。因为如果两个对象不相同,他们的hashCode值可能相同。
事实上,如果两个对象hashCode值相等,他们不一定相等;如果两个对象hashCode值不相等,他们一定不相等。
  Java中的HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键,这两个约束实际上就是通过hashCode()equals()方法来实现的。但具体是如何判断的呢,先看一个示例:

class Demo {
    @Override
    public boolean equals(Object obj) {
        System.out.println("进入equals>>>>>>>>>>>>>>>>>>>>>>");
        return false;
    }

    @Override
    public int hashCode() {
        System.out.println("进入hashCode>>>>>>>>>>>>>>>>>>>>");
        return 1;
    }
}

  Demo是自定义的一个类,重写了hashCode()equals()方法。以下是创建了一个Demo对象d1,并两次将该对象作为键传给HashMap,可以发现,第一次put()的时候,由于HashMap为空,所以只调用hashCode()方法而不会调用equals()方法。当第二次传入的时候调用的hashCode()返回的值与第一次相同,于是系统判断是重复的键,键值对插入失败,也不再继续调用equals()方法。

public class Solution {
    public static void main(String[] args) {
        HashMap<Demo, Integer> hashMap = new HashMap<>();
        Demo d1 = new Demo();
        hashMap.put(d1, 1);
        hashMap.put(d1, 2);
        System.out.println(hashMap.size());
    }
}

  以下为上述情况下的输出值。

进入hashCode>>>>>>>>>>>>>>>>>>>>
进入hashCode>>>>>>>>>>>>>>>>>>>>
1

  当创建两个不同的对象d1和d2的时候,插入d1的时候调用hashCode()方法之后正常加入键值对。插入d2的时候首先调用hashCode()方法,发现与d1的hash返回值不同,接着调用equals()方法,返回值为false,判断为不同的对象,所以将<d2,2>键值对成功插入HashMap。

public class Solution {
    public static void main(String[] args) {
        HashMap<Demo, Integer> hashMap = new HashMap<>();
        Demo d1 = new Demo();
        Demo d2 = new Demo();
        hashMap.put(d1, 1);
        hashMap.put(d2, 2);
        System.out.println(hashMap.size());
    }
}

  以下为上述情况下的输出值。

进入hashCode>>>>>>>>>>>>>>>>>>>>
进入hashCode>>>>>>>>>>>>>>>>>>>>
进入equals>>>>>>>>>>>>>>>>>>>>>>
2

  Java中的Set集合元素是不可重复的,要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals()方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,一一比较的话会大大降低效率。于是,Java采用了哈希表的原理,哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果想详细了解哈希算法,可以参考我的另一篇博客。hashCode()方法实际上返回的就是对象的地址。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode()方法,就能很快定位到它应该放置的物理位置上(时间复杂度为O(1))。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals()方法与新元素进行比较,相同的话就不再存储,如果不相同就散列其它的地址。所以,Java对于hashCode()方法和eqauls()方法是这样规定的:1、如果两个对象相同,那么它们的hashCode值一定要相同;2、如果两个对象的hashCode值相同,它们并不一定相同。

引申

  • "=="也可以比较,但是对于基本类型比较的是值,对于引用类型比较的是地址值。
  • Object类的equals()方法就是利用"=="进行判断的,所以新建的类需要重写equals()方法,否则调用equals()比较的也是地址值。
  • Object类中的hashCode()是返回对象在内存中地址转换成的一个int值。所以如果没有重写hashCode()方法,任何对象的hashCode值都是不相等的。
发布了28 篇原创文章 · 获赞 12 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/Carson_Chu/article/details/95466813