如果使用Object作为HashMap的Key,为什么要重写hashcode和equals

序言

读者需要了解HashMap底层存储数据结构 可参考文章

HashMap的put详解

如果使用Object作为HashMap的Key,为什么要重写hashcode和equals_第1张图片如果使用Object作为HashMap的Key,为什么要重写hashcode和equals_第2张图片
它是把key进行hash,然后存储,如果key是Object,并且没有重写hashcode,那么它将用物理地址进行hash,否则将使用对象值进行hash。
如果使用Object作为HashMap的Key,为什么要重写hashcode和equals_第3张图片
通过这张图我们可以看到put的具体操作。

if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
//这一步是第一次put时,会创建一个容量为16的数组,再次put就会直接重用
if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
/*这一步的hash是第二张图哈希后的结果,如果不重写hashCode的话,就算值相同
 *的Object也会因为物理地址不同导致hash值不同而直接存入。那是不是重写了
 *hashCode函数后,hash值相同就不会存入了。我们接着往下看····
 */
 if (p.hash == hash &&
             ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
//这一步非常关键 首先是hash值要相同,并且key.equals(k)也要为true
//如果我们不重写equals函数,导入值相同也会为false,因为比较的是地址

HashMap的get详解

如果使用Object作为HashMap的Key,为什么要重写hashcode和equals_第4张图片
调用的hash函数同图2,直接看getNode函数
如果使用Object作为HashMap的Key,为什么要重写hashcode和equals_第5张图片
第一个if条件很明显,首先是map被创建,其次tab数组存在相同的hash
第二个if条件和第三个if条件是在同一个hash下的链表寻找hash相同,并且值一样的对象。

总结

通过对源码进行分析我们可以知道,Object作为key时,不重写equals和hashCode函数,会将相同的对象(值相同)存入。在获取时也是先找相同的hash,再找值相同的对象。
如果不重写HashCode,无论equals重写与否,都是在table数组两个不同链表中;重写HashCode,不重写equals,则在table数组的同一个链表中;只有两个函数都重写,才能保证唯一性。

你可能感兴趣的:(如果使用Object作为HashMap的Key,为什么要重写hashcode和equals)