为什么HashMap的默认负载因子是0.75|Java 刷题打卡

499 阅读3分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

在了解完HashMap的扩容机制之后,我就会想起之前面试的时候,有一个面试官问我有没有了解过为什么负载因子是0.75的问题,忘了当时是怎么回答的,但是肯定回答的是不准确的,于是写下了这篇文章记录一下,加深一下印象,也希望能够帮助到你~

场景:基于JDK1.8

1、负载因子的作用

负载因子是和扩容机制有关的,意思是,如果当时容器的容量,达到了最大值(容量负载因子),就会进行扩容,例如当前容器的容量为16,那么可存放的最大值为 **160.75=12**,当容器存储的元素到达了12个,容器便会进行扩容操作 ​

2、 原因解释(重点)

我们在考虑HashMap的时候,首先想到的就是HashMap只是一个数据结构,既然是数据结构,那么最主要的就是节省时间和节省空间,负载因子的作用也肯定是节省空间和时间。为什么节省呢?我们考虑极端情况的两种场景

负载因子是1.0

image.png 这是HashMap的底层数据结构 我们的数据一开始是保存在数组里面的,当发生了Hash碰撞的时候,就是在这个数据的节点上,生出一个链表,当链表长度达到了一定长度的时候,就会把链表转化为红黑树。 当负载因子是1.0的时候,也就意味着,只有当数组的8个值(这个图表示了8个)全部填充了,才会发生扩容。这就带来了很大的问题,因为Hash冲突是避免不了的。当负载因子是1.0的时候,意味着会出现大量的Hash冲突,底层的红黑树变得异常复杂,对于查询效率极其不利。这种情况就是牺牲了时间来保证空间的利用率

因此,负载因子过大,虽然空间利用率上去了,但是时间效率降低了 ​

2、负载因子是0.5

负载因子是0.5的时候,这就意味着,当数组的元素到达了一半的时候就开始扩容,既然填充的元素少了,Hash冲突也会减少,那么底层的链表长度或者是红黑树的高度就会江都,查询效率就会提高。 但是,这时候空间利用率就会大大的降低,原本存储1M的数据,现在意味这需要2M的空间 ​

因此,负载因子太小,虽然时间效率提高,但是空间利用率降低了、 ​

3、负载因子0.75

经过极端情况的考虑,为什么默认值是0.75应该也就知道了,这是权衡时间和空间的。当然这个负载因子为什么是0.75其实在HashMap的源码里面也有解释。 image.png 此处我手敲一边,加深印象,翻译来自于Google翻译 通常,默认负载因子(.75)在时间和空间成本之间进行权衡。较高的值会降低空间开销,但是增加了查找的成本(在大多数情况下都反映了这一点),HashMap类的操作,包括get 和 put。预期的条目数映射及其负载系数应在以下情况下考虑设置其初始化容量,以最大程度的减少数量重新哈希操作。如果初始容量大于最大条目数除以负载系数,不重新哈希操作将永远发生。

下面我将HashMap的类注释翻译了一边,有兴趣的可以看一下

image.png