面试题专题:之hashMap的读写

120 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

摘要

本次分享面试题专题均为自己21届校招时通过牛客以及自己面试遇到的问题,答案均为自己理解整理,如果有错误,请麻烦评论指出,万分感谢,如对您有所帮助,请交出您的三连或者点赞也是爱♥

HashMap的读流程

jdk1.7读流程:

1.key是否为空值null,如果为空,直接遍历table[0]链表,寻找key==null键。调用的是getForNullKey()方法。如下:

1.1.如果元素个数为0,直接返回null。

1.2.遍历table[0]。

1.3.遍历到了,返回值;没遍历到,返回null。

2.key不为空,获取entry。调用getEntry方法。

2.1.如果元素个数为0,直接返回null。

2.2.计算hash。如果key为null,hash值是0;如果不为0,调用hash()方法。

2.3.计算索引位置。调用indexFor()方法。

2.4.遍历table[索引]。哈希相等,key相等(【==相等】或者【key不为空并且equals()相等】),这种情况就算找到了。

2.5.遍历到了,返回值;没遍历到,返回null。

3.如果entry为空,返回空;如果entry不为空,返回entry的value值。

jdk1.8读流程:

1.计算哈希。调用hash()方法。

2.调用getNode()方法获取node对象。

2.1.table数组已经初始化,长度大于0,根据hash寻找table中的项也不为空。

2.2.table[索引]中的first元素的key相等,直接返回node;不相等,执行下一步骤2.3。

2.3.如果first元素的next节点存在,继续下一步骤2.4。

2.4.如果first元素是TreeNode,调用getTreeNode()方法。

2.4.1.获取root节点。

2.4.2.调用find方法,获取TreeNode对象。

2.5.如果first元素不是TreeNode,遍历链表。

3.如果node对象为空,直接返回null;如果不为空,返回e.value。

HashMap的写流程

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.判断键值对数组table[i]是否为空或为null,如果是,执行resize()进行扩容;

2.2.根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向步骤2.6,如果table[i]不为空,转向步骤2.3;

2.3.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向步骤2.4,这里的相同指的是hashCode以及equals;

2.4.判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向步骤2.3;

2.5.遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可;

2.6.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容