final V put(K key, int hash, V value, boolean onlyIfAbsent) {
//
在
往
该
segment
写⼊
前
,
需
要
先
获
取
该
segment
的
独
占
锁
//
先
看
主
流
程
,
后
⾯
还
会
具
体
介
绍
这
部
分
内
容
HashEntry<K,V> node = tryLock() ? null :
scanAndLockForPut(key, hash, value);
V oldValue;
try {
//
这
个
是
segment
内
部
的
数
组
HashEntry<K,V>[] tab = table;
//
再
利
⽤
hash
值
,
求
应
该
放
置
的
数
组
下
标
int index = (tab.length - 1) & hash;
// first
是
数
组
该
位
置
处
的
链
表
的
表
头
HashEntry<K,V> first = entryAt(tab, index);
//
下
⾯
这
串
for
循
环
虽
然
很
⻓
,
不
过
也
很
好
理
解
,
想想
该
位
置
没
有
任何
元
素
和
已
经
存
在
⼀个
for (HashEntry<K,V> e = first;;) {
if (e != null) {
K k;
if ((k = e.key) == key ||
(e.hash == hash && key.equals(k))) {
oldValue = e.value;
if (!onlyIfAbsent) {
//
覆
盖
旧
值
e.value = value;
++modCount;
}
break;
}
//
继续
顺
着
链
表
⾛
e = e.next;
}
else {
// node
到
底
是
不
是
null
,
这
个
要
看
获
取
锁
的
过
程
,
不
过
和
这
⾥
都
没
有
关
系
。
//
如
果
不为
null
,
那
就
直
接
将
它
设
置
为
链
表表
头
;
如
果
是
null
,
初
始
化
并
设
置
为
if (node != null)
node.setNext(first);
else
node = new HashEntry<K,V>(hash, key, value, first);
int c = count + 1;
//
如
果
超
过
了
该
segment
的
阈
值
,
这
个
segment
需
要
扩
容
if (c > threshold && tab.length < MAXIMUM_CAPACITY)
rehash(node);
//
扩
容
后
⾯
也
会
具
体
分
析
else