HashMap实现原理和自动扩容

2023-05-24,,

HashMap实现原理

JDK1.7:数组+单向链表(头插)

在并发情况下头插可能出现循环链表(死循环)问题。原因:因为头插,在新数组中链表的元素顺序发生了变化,

如上图,假设线程1在扩容,刚刚调整链表完毕;线程2的指针却指向的还是原来的元素。这时新数组链表中是1->2->3的指向,但是线程2却是调整(扩容)前的3->2指向

JDK1.8:数组+单向链表(尾插)+红黑树

HashMap中数组的大小有什么特点?

初始化时数组的容量是2的幂次方数,即16;

如果初始化时指定数组大小,比如17,则实际数组大小是>17的2的幂次方数,即32.

HashMap中如何计算数组下标?

HashMap的键值对组成了数组,数组就有下标索引问题。需要根据key来计算当前key-value在数组中的位置:

可以看到,通过哈希值和(数组长度-1)的与操作【位运算】(代替取余)来计算数组下标,这种位运算要求数组大小必须为2的幂次方。

奇数做位运算时,高位一定是0;奇数和哈希值做位运算,结果取决于哈希值的低位。

为何用二次哈希结果计算索引?为了让计算索引的hashcode值分布得更加均匀。

假设数组长度是10,现在有80个元素都有哈希冲突,理想情况是每个数组位,存1个元素+7个元素长度的链表。这就是分布均匀。

分布不均匀:某些链表非常长(被迫转换成红黑树),某些链表过短。

更多关于二次哈希移步

(JDK1.8为右移16位)

如何解决Hash冲突

上一篇文章有简单说明。

何时触发自动扩容机制

数组扩容因子=0.75

链表的长度>8 & 数组长度>=64,==>红黑树

红黑树生成时Node-->TreeNode的转变,同时会将单向链表转变成双向链表。

*本篇暂不阐述HashMap并发相关知识点。后续单独开新篇。

HashMap实现原理和自动扩容的相关教程结束。

《HashMap实现原理和自动扩容.doc》

下载本文的Word格式文档,以方便收藏与打印。