可以看出这是一个单链表结构,存放着 hash、key和value
- resize() 函数,作用:初始化或者扩容表为原大小的2倍。源码后面再分析。
- 知道以上的信息我们在看 putVal() 函数的代码,注释1
if ((tab = table) == null || (n = tab.length) == 0)//注释1
n = (tab = resize()).length;
我们知道DEFAULT_INITIAL_CAPACITY = 1 << 4 // aka 16
因此可以知道
tab = (Node<K,V>[])new Node[16]
和 n = 16
- 接着往下看,注释2
if ((p = tab[i = (n - 1) & hash]) == null) //注释2
tab[i] = newNode(hash, key, value, null);
我们是第一次调用,p = tab[i = (n - 1) & hash]
肯定是null ,于是我们这次就成功的把key,value 存到了tab[i]
中。
- 我们走进了if,else 的代码就不用看了,直接到了//注释3 的位置
++modCount
用于记录修改的次数,接着往下看:
if (++size > threshold)
resize();
threshold
为扩容阈值,初始化时为 DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR //aka 16*0.75 = 12
, size 为HashMap 中保存 Node的数量,当等于 扩容阈值 时就需要对 tab 进行扩容。
接着往下是 afterNodeInsertion(evict);
这是一个空方法,什么都没做。
void afterNodeInsertion(boolean evict) { }
好了,我们第一次调用就结束了。成功的把数据存储到了HashMap 中,再回头看下我们之前没有看的 else 中的情况
else 中的情况
当tab[i = (n - 1) & hash]
中已经有值的情况就会走到 else 中,看代码:
static final int TREEIFY_THRESHOLD = 8;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
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 = newN