Java面试题:HashMap基本原理
Posted 会写代码的鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试题:HashMap基本原理相关的知识,希望对你有一定的参考价值。
描述一下HashMap数据结构
HashMap采用了Hash数组加链表的数据结构。首先通过key计算出对应的Hash值,然后定位到Hash数组中的位置,如果出现Hash冲突(不同的key可能计算出相同的Hash值),则使用链表把这些具有相同Hash值的元素串起来,后加入的数据存放在链表的头部。如果单个链表上的元素大于8个的化,还会使用红黑树来代替单向链表。
数据结构如下图:
HashMap数据结构
关键点:
HASH数组。
链表存放HASH冲突的元素。
链表长度大于8使用红黑树进行优化。
为了快速计算出具体HASH对应到元素中的位置,使用(n - 1) & hash计算。
数组长度必须是2的x次方,HashMap内部会强制保证这一点。
HashMap为什么需要扩容,在什么情况下会进行扩容。
默认情况下,HashMap的Hash数组的长度为16,理论上每一个链表可以无限长,也就是说理论上可以不需要进行扩容就能够存放任意多的数据(内存允许的化),如果真的是这样,那当数据量上去以后查询一个数据将会是一种灾难。
我们来看一下HashMap中查询数据的过程:
1、通过Hash定位到数组的具体位置,
2、遍历列表然后比对key值,key相同的就是要查找的元素。如果Hash数组的长度一定,则随着map中的数据增加链表的长度会越来越长,遍历的效率也就越来越低。通过扩容Hash数组则可以有效的降低链表的长度,以提高HashMap的效率。
那么HashMap是如何决定需要扩容的呢?
在HashMap中存在一个扩容阈值:loadFactor,默认情况下为0.75。当Map中的数据个数大于Hash数组长度乘以loadFactor的时候就会进行扩容。
HashMap扩容过程,假设扩容前的数组长度为n:
1、计算新的数组长度,一般为原来长度的两倍(使用右移一位来完成)。
2、重新计算每一个元素的位置。对于第j个槽的元素,(hash & n) == 0还是存放在第j个槽的位置,(hash & n) == 1则放在(n+j)个槽的位置,具体原因大家可以自己分析一下(这是一个非常巧妙的计算)。
以上是关于Java面试题:HashMap基本原理的主要内容,如果未能解决你的问题,请参考以下文章