首先贴 java 8 中实现的源代码
1 /** Implementation for put and putIfAbsent */ 2 final V putVal(K key, V value, boolean onlyIfAbsent) { 3 if (key == null || value == null) throw new NullPointerException(); 4 int hash = spread(key.hashCode()); 5 int binCount = 0; 6 for (Node<K,V>[] tab = table;;) { 7 Node<K,V> f; int n, i, fh; 8 if (tab == null || (n = tab.length) == 0) // 第一次使用时,整个 table 为 null 9 tab = initTable(); 10 else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { 11 if (casTabAt(tab, i, null, 12 new Node<K,V>(hash, key, value, null))) 13 break; // no lock when adding to empty bin 14 } 15 else if ((fh = f.hash) == MOVED) // 当节点的 hash 值为 -1 时,代表这个节点为 ForwardingNode, 其后续节点需要转移 16 tab = helpTransfer(tab, f); 17 else { 18 V oldVal = null; 19 synchronized (f) { 20 if (tabAt(tab, i) == f) { // 再次获得热区代码执行权后,首先确保之前记录的第 i 个节点没有变化(即没被迁移走) 21 if (fh >= 0) { // 确保当前节点的 hash 值代表正常的节点(其他的辅助型节点,比如 ForwardingNode,TreeBin,ReservationNode) 22 binCount = 1; 23 for (Node<K,V> e = f;; ++binCount) { 24 K ek; 25 if (e.hash == hash && 26 ((ek = e.key) == key || 27 (ek != null && key.equals(ek)))) { // 判断目标节点的根据是 spread 后的hash值相同并且(key 的 reference 相同或者 key 相等) 28 oldVal = e.val; 29 if (!onlyIfAbsent) 30 e.val = value; 31 break; 32 } 33 Node<K,V> pred = e; 34 if ((e = e.next) == null) { // 如果到达当前链表的尾节点,则 append 新的元素 35 pred.next = new Node<K,V>(hash, key, 36 value, null); 37 break; 38 } 39 } 40 } 41 else if (f instanceof TreeBin) { // 当 fh 小于 0,且为 -2 时,此时元素类型为 TreeBin 42 Node<K,V> p; 43 binCount = 2; 44 if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, 45 value)) != null) { 46 oldVal = p.val; 47 if (!onlyIfAbsent) 48 p.val = value; 49 } 50 } 51 } 52 } 53 if (binCount != 0) { 54 if (binCount >= TREEIFY_THRESHOLD) // 当插入元素后,单个 slot 的链表的节点数目大于等于 8 时,进行红黑树化这个 slot 55 treeifyBin(tab, i); 56 if (oldVal != null) 57 return oldVal; 58 break; 59 } 60 } 61 } 62 addCount(1L, binCount); 63 return null; 64 }
a
原文:https://www.cnblogs.com/neocxf/p/12581015.html