HashMap的一些底层知识点
作者:互联网
- HashMap的底层数据结构?
数字+链表+红黑树
-
HashMap的存取原理?
①.判断键值对数组table[i]是否为空或为null,否则执行resize()进行扩容;
②.根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向⑥,如果table[i]不为空,转向③;
③.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals;
④.判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤;
⑤.遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可;
⑥.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容。
-
为啥会线程不安全?
1.7中在并发的多线程使用场景中使用HashMap可能造成死循环。1.8中put/get方法都没有加同步锁,多线程情况最容易出现的就是:无法保证上一秒put的值,下一秒get的时候还是原值,所以线程安全还是无法保证。
-
默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?
初始化大小是16,当你调用它的空构造器时
- HashMap的扩容方式?负载因子是多少?为什是这么多?
1.7中:首先会创建一个新的entry数组,大小为原来的两倍,然后将重新对旧数组的每个元素的位置,进行添加,遇到哈希碰撞将使用头插法。1.8中:将不在对每个元素重新计算hash的值只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”。同时它也变成了尾插法
负载因子0.75。
threshold就是在此Load factor和length(数组长度)对应下允许的最大元素数目,超过这个数目就重新resize(扩容),扩容后的HashMap容量是之前容量的两倍。默认的负载因子0.75是对空间和时间效率的一个平衡选择,建议大家不要修改,除非在时间和空间比较特殊的情况下,如果内存空间很多而又对时间效率要求很高,可以降低负载因子Load factor的值;相反,如果内存空间紧张而对时间效率要求不高,可以增加负载因子loadFactor的值,这个值可以大于1。
- HashMap的主要参数都有哪些?
transient Node<K,V>[] table; //存储键值对的数列
transient int size //键值对的数量
int threshold; //数组扩容的临界值
final float loadFactor; //负载因子
-
hash的计算规则?
先算出key的hashcode,然后用此hashcode与(hashcode >>> 16)相与也就是和它的高16位做与运算,最后再对table的长度进行取模。
可以看看美团技术团队的这篇文章https://zhuanlan.zhihu.com/p/21673805
标签:知识点,负载,HashMap,链表,键值,数组,table,底层 来源: https://www.cnblogs.com/xiaoovo/p/16585456.html