只要覆写equals,就必须覆写hashCode;set,hashset存值的过程

只要覆写equals,就必须覆写hashCode
阿里的开发手册中是写了这么两句话:
(1)因为Set 存储的是不重复的对象,依据 hashCode和equals进行判断,所以 Set 存储的对象必须覆 写这两个方法。
(2)如果自定义对象作为Map 的键,那么必须覆写hashCode 和equals
下面我来解释一下:
先看这段代码

public static void main(String[] args) {
        Set set = new HashSet();
        String str1 = new String("Evan");
        String str2 = new String("Evan");
        set.add(str1);
        set.add(str2);
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));
        System.out.println(set.size());
    }

那么它打印的结果是多少呢
false
true
1
很明显str1和str2是不同的两个的对象,但是set存的值却只有一个这是为什么呢,因为string重写了equals和hashcode方法

        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());
     	2172094
		2172094

当我们往一个空的Set集合中加入数据时,第一次加入的数据会直接加入到集合中,从第一个往后所有要加入的数据会和集合里的数据进行比较。而且会先比较当前加入数据的hashCode()的值是否在set集合中存在,如果没有重复,那么就会认为这是两个不同的数据 就会直接加入。但是如果hashCode()的值相同,就会再调用equals()方法来比较,如果也相同那么就认为是一个数据,否则就是两个数据。而且当hashCode()的值不同是就不会继续调用equals()了。
上面代码的str1和str2因为string重写了equals和hashcode两者比较都是相同的,故set去重,只存入了一个值。
解释一下为何先要比较hashCode()值是否相等,然后再用equals()进行比较。
hashCode()方法和equal()方法的作用在Java里都是用来对比两个对象是否相等一致。假如用equals(),那么存储一个元素就要跟已存在的所有元素比较一遍,比如已存入100个元素,那么存101个元素的时候,就要调用equals方法100次,重写的equal()方法底层实现里一般比较复杂,从而效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。但是利用hashCode()进行比较时会存在一个问题,有两个不相等的数据在生成hash值时偶尔会相等。所以需要再次调用equal()方法进行比较。这样比较既能提高效率又能确保准确性。
再说一下hashset存值的顺序:hashset存值,首先他会判断该对象的hash值在hashset集合中是否存在(自定义对象要自己实现hashcode方法和equals方法,String等已经实现不需要自己再实现),如果不存在则存入集合(这个时候就用到它的数据结构了,数组!其实存入的就是数组),如果存在相同的hash值,即哈希碰撞,则判断equals方法,相同就不存,如果不同,则证明,该集合中存在与该对象相同的hash值但是值不同的对象,就会再判断它是否有树结点,有就转换为红黑树,否则,就存入链表,如果链表值(即哈希碰撞值)大于8就会转换为红黑树。

发布了1 篇原创文章 · 获赞 2 · 访问量 14

猜你喜欢

转载自blog.csdn.net/weixin_46200547/article/details/104006016