JDK7 与 JDK8 中HashMap 的实现

JDK7 中的 HashMap

HashMap 底层维护一个数据,数组中存放的是 Entry<K, V>。
Map中的key,value则以Entry的形式存放在数组中。

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        int hash;
}

通过计算 key 的 hash 值来决定放在数组的哪个位置,当 hash 值冲突时,用链表的方式来存储。
数组扩容是原来的一倍。
如果 key 为 null,会将这个元素存放到 table[0] 的位置。
在这里插入图片描述

JDK8 中的 HashMap

JDK8 采用的是数组+链表/红黑树的方式,当链表的长度大于某个阈值(默认是8)时,会将链表转化成红黑树。红黑树的查询数据远大于链表。
JDK8中,当同一个hash值的节点数不小于8时,将不再以单链表的形式存储了,会被调整成一颗红黑树。这就是JDK7与JDK8中HashMap实现的最大区别。
在这里插入图片描述
JDK中Entry的名字变成了Node,原因是和红黑树的实现TreeNode相关联。
源码解析:

 public V put(K key, V value) {
     return putVal(hash(key), key, value, false, true);
 }

 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
     Node<K, V>[] tab;
     Node<K, V> p;
     int n, i;
     // 如果当前 map 中无数据,执行 resize 方法创建 Node<K,V>[] 数组存放 Entry<K,V> 数据
     if ((tab = table) == null || (n = tab.length) == 0)
         n = (tab = resize()).length;
     // 如果要插入的键值对要存放的这个位置刚好没有元素,那么把数据封装成 Node 对象后存放在该位置
     if ((p = tab[i = (n - 1) & hash]) == null)
         tab[i] = newNode(hash, key, value, null);
     // 否则说明该位置有元素
     else {
         Node<K, V> e;
         K k;
         // 如果要插入元素的key和该位置一样,那么久替换一下
         if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
             e = p;
         // 如果当前节点是 TreeNode 类型的数据,执行 putTreeVal 方法
         else if (p instanceof TreeNode)
             e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);
         // 表示当前节点是链表结构,插入链表的最后面
         else {
             for (int binCount = 0;; ++binCount) {
                 if ((e = p.next) == null) {
                     p.next = newNode(hash, key, value, null);
                     // 判断key的hash冲突是否超过链表最大值的阈值,超过的话,将链表转换成  TreeNode(红黑树结构)
                     if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                         treeifyBin(tab, hash);
                     break;
                 }
                 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
                     break;
                 p = e;
             }
         }
         if (e != null) { // existing mapping for key
             V oldValue = e.value;
             if (!onlyIfAbsent || oldValue == null)
                 e.value = value;
             afterNodeAccess(e);
             return oldValue;
         }
     }
     ++modCount;
     if (++size > threshold)
         resize();
     afterNodeInsertion(evict);
     return null;
 }

参考:
https://www.cnblogs.com/wihainan/p/7047718.html

猜你喜欢

转载自blog.csdn.net/const_/article/details/89374180