HashMap插入节点详细过程
Posted 小谢backup
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap插入节点详细过程相关的知识,希望对你有一定的参考价值。
下面先给出HashMap的草图,方便理解:
Java1.8中HashMap插入的过程流程图如下:
大致总结一下,除了特殊情况判断之外,插入节点到HashMap过程中,首先计算节点的哈希后找到对应的位置(槽),如果该槽为空,直接插入即可,否则顺着该槽沿伸出来的链表或者红黑树遍历到尾部然后插入,如果中途遇到相同key冲突的情况就替换掉旧的Node。
具体代码实现如下(已做部分注释):
1 /**
2 * 插入新节点
3 * @param onlyIfAbsent 只有槽为空的情况才插入,遇到相同key冲突的情况不可替换(即舍弃要插入的node),put时为false
4 */
5 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
6 boolean evict) {
7 Node<K,V>[] tab; Node<K,V> p; int n, i;
8
9 if ((tab = table) == null || (n = tab.length) == 0)//如果map为空,直接扩容后返回
10 n = (tab = resize()).length;
11
12 if ((p = tab[i = (n - 1) & hash]) == null)//如果槽为空,直接放入
13 tab[i] = newNode(hash, key, value, null);
14 else {
15 Node<K,V> e; K k;
16 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))//槽中node的key与插入node的key相等,直接到下面的if (e != null) 语句块
17 e = p;
18 else if (p instanceof TreeNode)//属于红黑树节点,按红黑树的方式插入
19 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
20 else {//分支链表形式插入
21 for (int binCount = 0; ; ++binCount) {//dead loop,条件在内部,binCount表示链表长度(从0开始)
22 if ((e = p.next) == null) {//短链表的最后一个节点,则插入,插入后判断是否应该转为红黑树,完成。
23 p.next = newNode(hash, key, value, null);
24 if (binCount >= TREEIFY_THRESHOLD - 1)//如果长度为8,转为红黑树
25 treeifyBin(tab, hash);
26 break;//完成插入后退出
27 }
28 if (e.hash == hash &&
29 ((k = e.key) == key || (key != null && key.equals(k))))//链或者树已有相同key存在,退出??
30 break;
31 p = e;
32 }
33 }
34
35 if (e != null) { // 槽中node(p)的key与插入node的key相等,直接覆盖该槽的node(直接换新值就好了)
36 V oldValue = e.value;
37 if (!onlyIfAbsent || oldValue == null)
38 e.value = value;//覆盖旧值
39 afterNodeAccess(e);
40 return oldValue;
41 }
42 }
43
44 //必做善后
45 ++modCount;
46 if (++size > threshold)//插入后预先判断是否下一次插入会不会越界,如果会就扩容
47 resize();
48 afterNodeInsertion(evict);
49 return null;
50}
以上是关于HashMap插入节点详细过程的主要内容,如果未能解决你的问题,请参考以下文章