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基本原理的主要内容,如果未能解决你的问题,请参考以下文章

Java面试题HashMap的底层实现原理

Java面试题|为什么基本类型不能做为HashMap的键值?

Java面试题HashMap的底层原理和线程安全的替代方案

Java集合---面试题

Java面试题8 | 图解LinkedHashMap原理

JAVA干货HashMap的工作原理