这个问题,主要参考的程序员小灰的博客:
一:简单的介绍一下啊HashMap:
1.1:HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。
1.2:计算位置:对key.hashCode进行hash运算,得到的值进行位运算。
1.3:HashMap数组的每一个元素不止是一个Entry对象,也是一个链表的头节点。每一个Entry对象通过Next指针指向它的下一个Entry节点。当新来的Entry映射到冲突的数组位置时,只需要插入到对应的链表即可;
需要注意的是,新来的Entry节点插入链表时,使用的是“头插法,也就是查到链表的头部,是因为HashMap的发明者认为,后插入的Entry被查找的可能性更大。
1.4:初始长度是16,并且每次扩展时候,长度必须是2的幂。因为2的幂-1对应的二进制末尾总是是1111,这样,和key.hash做“与”运算的时候,只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。
二:高并发下的HashMap
2.1:当 HashMap.Size >= Capacity * LoadFactor 时候,HashMap进行Resize
影响发生Resize的因素有两个:
1.Capacity
HashMap的当前长度。上一期曾经说过,HashMap的长度是2的幂。
2.LoadFactor
HashMap负载因子,默认值为0.75f。
也就是现有长度(size)是目前容量的0.75的时候,扩容。
2.2:Resize步骤:
1.扩容
创建一个新的Entry空数组,长度是原数组的2倍。
2.ReHash
遍历原Entry数组,把所有的Entry重新Hash到新数组。为什么要重新Hash呢?因为长度扩大以后,Hash的规则也随之改 变。
让我们回顾一下Hash公式:
index = HashCode(Key) & (Length - 1)
当原数组长度为8时,Hash运算是和111B做与运算;新数组长度为16,Hash运算是和1111B做与运算。Hash结果显然不同。
2.3:reHash带来的问题
看代码:
网友评论