jdk7的put过程
- 先判断key是否为null,如为null则调用putfornullkey(value)方法,在数组的表头位置插入或覆盖null kye的值;
- 根据键值key计算hash值得到插入的数组索引;
- 若该索引位置有值,则遍历该处的链表,若链表操作相同key,则覆盖并返回旧值;
- 若key对应桶位位null,或者链表中没有相同的key,则将修改计算加一;
- 判断实际存在的键值对数量size是否大于阈值,若大于则进行扩容并重新计算key对应新数组的桶位;
- 最后向对应桶位的表头插入新值,size加一。
jdk7的resize过程
- 先判断原数组的大小是否已经到达最大值,若已经到达最大值,则将阈值设为int的最大值,然后返回,至此以后该HashMap就不会再进行扩容了;
- 初始化一个新的entry数组,数组大小为原数组的两倍;
- 将原数组的数据转移至新数组里,转移的过程为:
- 遍历数组,查询计算桶位,并已头插发插入新数组对应的位置,若当前位置是个链表,则继续遍历链表
- 最后将新数组的引用赋给table变量,并继续新的阈值。
jdk8的put过程
①.判断键值对数组是否为空或为null,若条件成立则执行resize()进行扩容;
②.根据键值key计算hash值得到插入的数组索引,如果索引位置的值为null,直接新建节点添加,转向⑥,如果不为空,转向③;
③.判断桶位的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals;
④.判断桶位是否为treeNode,即该节点是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤;
⑤.遍历该桶位的节点,判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作(这里用的尾插发);遍历过程中若发现key已经存在直接覆盖value即可;
⑥.插入成功后,判断实际存在的键值对数量size是否超过阈值,如果超过,进行扩容。