源码:
1 public V put(K key, V value) {
2 return putVal(key, value, false);
3 }
4
5 /** Implementation for put and putIfAbsent */
6 final V putVal(K key, V value, boolean onlyIfAbsent) {
7 //ConcurrentHashMap 不允许插⼊null键,HashMap允许插⼊⼀个null键
8 if (key == null || value == null) throw new NullPointerException();
9 //计算key的hash值
10 int hash = spread(key.hashCode());
11 int binCount = 0;
12 //for循环的作⽤:因为更新元素是使⽤CAS机制更新,需要不断的失败重试,直到成功为⽌。
13 for (Node<K,V>[] tab = table;;) {
14 // f:链表或红⿊⼆叉树头结点,向链表中添加元素时,需要synchronized获取f的锁。
15 Node<K,V> f; int n, i, fh;
16 //判断Node[]数组是否初始化,没有则进⾏初始化操作
17 if (tab == null || (n = tab.length) == 0)
18 tab = initTable();
19 //通过hash定位Node[]数组的索引坐标,是否有Node节点,如果没有则使⽤CAS进⾏添加(链表的头结点),添加失败则进⼊下次循环。
20 else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
21 if (casTabAt(tab, i, null,
22 new Node<K,V>(hash, key, value, null)))
23 break; // no lock when adding to empty bin
24 }
25 //检查到内部正在移动元素(Node[] 数组扩容)
26 else if ((fh = f.hash) == MOVED)
27 //帮助它扩容
28 tab = helpTransfer(tab, f);
29 else {
30 V oldVal = null;
31 //锁住链表或红⿊⼆叉树的头结点
32 synchronized (f) {
33 //判断f是否是链表的头结点
34 if (tabAt(tab, i) == f) {
35 //如果fh>=0 是链表节点
36 if (fh >= 0) {
37 binCount = 1;
38 //遍历链表所有节点
39 for (Node<K,V> e = f;; ++binCount) {
40 K ek;
41 //如果节点存在,则更新value
42 if (e.hash == hash &&
43 ((ek = e.key) == key ||
44 (ek != null && key.equals(ek)))) {
45 oldVal = e.val;
46 if (!onlyIfAbsent)
47 e.val = value;
48 break;
49 }
50 //不存在则在链表尾部添加新节点。
51 Node<K,V> pred = e;
52 if ((e = e.next) == null) {
53 pred.next = new Node<K,V>(hash, key,
54 value, null);
55 break;
56 }
57 }
58 }
59 //TreeBin是红⿊⼆叉树节点
60 else if (f instanceof TreeBin) {
61 Node<K,V> p;
62 binCount = 2;
63 //添加树节点
64 if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
65 value)) != null) {
66 oldVal = p.val;
67 if (!onlyIfAbsent)
68 p.val = value;
69 }
70 }
71 }
72 }
73
74 if (binCount != 0) {
75 //如果链表⻓度已经达到临界值8 就需要把链表转换为树结构
76 if (binCount >= TREEIFY_THRESHOLD)
77 treeifyBin(tab, i);
78 if (oldVal != null)
79 return oldVal;
80 break;
81 }
82 }
83 }
84 //将当前ConcurrentHashMap的size数量+1
85 addCount(1L, binCount);
86 return null;
87 }