1.putVal方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab
//表格为空或者表格的大小为0的话,进行扩容
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length
if ((p = tab[i = (n - 1) & hash]) == null)
// (n - 1) & hash相当于 hash % n - 1,这里可以做&是因为表格的大小是 2的n次方- 1, X % length = X & (length - 1)
// 如果表格给定位置为空,那么就创建新的节点
tab[i] = newNode(hash, key, value, null)
else {
Node<K,V> e
//(k = p.key) == key || (key != null && key.equals(k)) 对象相等,那么他们的hash值一定相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
// 如果key值并且hash值都相等,那么就让e把表头节点带出来
e = p
else if (p instanceof TreeNode)
// 如果是树节点,那么就插入到红黑树中
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value)
else {
// 循环查找链表节点
for (int binCount = 0
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null)
// 尾插法,找到链表尾部插入一个节点之后,那么就需要看是否树化
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash)
// 不用树化的话就推出
break
}
// 查找链表的过程中,发现有key相同的节点,那么直接退出,注意这时候e是指向当前相等的节点了
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
}
2.resize方法
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table
//oldCap获取原有表的大小,如果原有表为空的情况下,大小设置为0
int oldCap = (oldTab == null) ? 0 : oldTab.length
int oldThr = threshold
int newCap, newThr = 0
if (oldCap > 0) {
// oldCap的值大于0
if (oldCap >= MAXIMUM_CAPACITY) {
//oldCap的门限值大于门限值的最大容量,直接返回,门限值不变
threshold = Integer.MAX_VALUE
return oldTab
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 容量在最大容量内,容量扩大两倍
// 门限值是否扩大两倍,那么就要看oldCap是否小于最大容量和大于16
newThr = oldThr << 1
}
else if (oldThr > 0) // initial capacity was placed in threshold
// 容量为0,并且门限值大于0的情况,那么newCap容量就是门限值
newCap = oldThr
else { // zero initial threshold signifies using defaults
//门限值和容量都是0
newCap = DEFAULT_INITIAL_CAPACITY
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY)
}
if (newThr == 0) {
// 新门限值的情况会在第一步if的时候, oldThr = 0的情况下出现
float ft = (float)newCap * loadFactor
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE)
}
threshold = newThr
// 创建了新表
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]
table = newTab
if (oldTab != null) {
// 将就表的元素移动至新表,有一个再hash的过程
for (int j = 0
Node<K,V> e
if ((e = oldTab[j]) != null) {
// 表头元素为空的情况下跳过,进行下一次循环
oldTab[j] = null
if (e.next == null)
// 只有表头有元素
newTab[e.hash & (newCap - 1)] = e
else if (e instanceof TreeNode)
// 如果是e是红黑树的元素
((TreeNode<K,V>)e).split(this, newTab, j, oldCap)
else { // preserve order
// 如果是链表中的元素
Node<K,V> loHead = null, loTail = null
Node<K,V> hiHead = null, hiTail = null
Node<K,V> next
//再hash结果值不同的分开成两组链表,尾插法
do {
next = e.next
//e.hash & oldCap很巧妙
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e
else
loTail.next = e
loTail = e
}
else {
if (hiTail == null)
hiHead = e
else
hiTail.next = e
hiTail = e
}
} while ((e = next) != null)
if (loTail != null) {
loTail.next = null
newTab[j] = loHead
}
if (hiTail != null) {
hiTail.next = null
newTab[j + oldCap] = hiHead
}
}
}
}
}
return newTab
}