HashMap为什么要同时重写hashCode和equals方法

今天说说HashMap为什么要同时重写hashCode和equals方法 , 为什么不只重写hashCode或者只重写equals呢 ? 算是自己也写个笔记记录记录吧 ! 

首先是hashmap的put方法 , 这个put方法的过程一定是要保证hashmap的键值对的唯一性 、 键的唯一性 。

 

hashmap 初始化的时候是一个table 数组  , 默认是16大小 , 然后如果有了hash冲突每一个键值对的下方会有一个链表进行hash冲突的解决方式 , 这里不说为什么了 , 主要讲重写问题 。 

假如只重写hashcode , 不重写equals : 

put ("a" ,"123")  ;   --->  存这个的时候调用key 的hashCode , 因为Object的hashcode返回的是内存地址 ,如果不重写hashcode , 那么同样的一个键值对 , 唯一性得不到保证 。

假设上方put ("a" ,"123")  ; put成功 ,如果这个时候继续调用一次put ("a" ,"123")  ;那么如果没有重写hashCode , 则此时两者都用的Object的hashcode去返回内存地址 , 两者hashcode比较肯定是不同的 ,原因在于不是同一个对象 。

则存储的情况是这样的 : 假设table 长度为 6 


 

1 2 3 4 5 6
(a , 123)   (a,123)      
           

所以不重写Object的hashcode ,那么键值对的唯一性无法保证 , 针对同一个key , 因为是不同对象 ,所以hashcode肯定是不同的。放的位置就会不同 。 

那么这里介绍了一定要重写hashcode , 保证键值对的唯一性 。

下面说说为什么也要重写equals呢 , 首先说说object 的equals 是 比较是否为同一个对象 , 即内存地址是否一样 。

此时我还是 put ("a" ,"123") ; 接着我在put ("b" ,"123") ;两次put 元素 ,假设这两次put的时机刚好key的hash 命中了 ,即发生了hash冲突 , 那么按照hashmap的解决方式 , 用了链表进行冲突位置的连接 , 存储情况如下:

1 2 3 4 5 6
(a,123)          
(b,123)          

那么两者都放在了1号位置 , 并且两者通过一个链表进行连接 , 即(a,123) 的下一个元素就是(b,123)  ;这种情况我假如调用一次get方法 -》 get(a)  ; 

那么执行过程是 对 a 进行hashcode 的判断 ,知道是在1号位置 , 那么去1号位置 , 发现有两个元素,

一个是(a,123)  、一个是(b,123) , 那我应该怎么判断呢 ? 肯定是用equals 进行判断 。

这是重写的源码:

public boolean equals(Object o) {
    if (o == this)
        return true;

    if (!(o instanceof Map))
        return false;
    Map m = (Map) o;
    if (m.size() != size())
        return false;

    try {
        Iterator> i = entrySet().iterator();
        while (i.hasNext()) {
            Entry e = i.next();
            K key = e.getKey();
            V value = e.getValue();
            if (value == null) {
                if (!(m.get(key)==null && m.containsKey(key)))
                    return false;
            } else {
                if (!value.equals(m.get(key)))
                    return false;
            }
        }
    } catch (ClassCastException unused) {
        return false;
    } catch (NullPointerException unused) {
        return false;
    }

    return true;
}

不仅仅判断key是否相等 , 还要判断value也要相等 。
 

 

结论 : 通过重写的hashcode 直接定位到key 的位置 , 根据重写的equals 保证唯一性。

你可能感兴趣的:(JAVA)