福哥答案2021-01-22:
jdk1.7写流程:
1.如果table数组为空,table数组初始化,调用inflateTable方法。
2.如果key为null,调用putForNullKey()方法,表示插入一个键为null的键值对。否则就是步骤3。
3.根据key计算hash,调用hash()方法。
4.计算下标,调用indexFor()方法。
5.遍历链表,如果找到元素,直接替换旧值。然后调用recordAccess()空方法。
6.没找到元素时,modCount自增。
7.新增元素,调用addEntry()方法。
7.1.是否需要扩容。size是否大于阈值,当前传入的下标在table中的位置不为null。如果不需要扩容,跳到步骤7.4。
7.2.扩容,调用resize()方法。
7.3.调用hash()计算哈希,调用indexFor()计算下标。
7.4.创建新的Entry节点。调用createEntry()方法。
7.4.1.获取table新索引
7.4.2.创建一个新的Entry对象,新索引位置的元素作为新的Entry对象的next元素,也就是说是头插法,然后赋值给table新索引。
7.4.3.长度加1。
jdk1.8写流程:
1.计算hash。调用hash()方法。
2.调用putVal()方法。
2.1.判断键值对数组tablei是否为空或为null,如果是,执行resize()进行扩容;
2.2.根据键值key计算hash值得到插入的数组索引i,如果tablei==null,直接新建节点添加,转向步骤2.6,如果tablei不为空,转向步骤2.3;
2.3.判断tablei的首个元素是否和key一样,如果相同直接覆盖value,否则转向步骤2.4,这里的相同指的是hashCode以及equals;
2.4.判断tablei 是否为treeNode,即tablei 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向步骤2.3;
2.5.遍历tablei,判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可;
2.6.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容。
HashMap源码分析(jdk7)
JDK1.8中的HashMap实现
评论