HashMap的负载因子为什么默认是0.75?这篇文章告诉你答案

HashMap之resize详解 文章目录1. 导读2. HashMap为什么要扩容3. HashMap何时扩容3. 为什么是0.754. HashMap如何扩容5. JDK8对JDK7的优化 1. 导读 上期分享了HashMap的key定位以及数据节点的设计, 本期就下面三个问题来分享下个人对于HashMap扩容的理解: .1 HashMap为什么要扩容? 何时扩容? .2 负载因子为什么是0.75? .3 HashMap如何扩... 阅读详情

前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75。

HashMap源码中的加载因子

static final float DEFAULT_LOAD_FACTOR = 0.75f;  

当时想到的是应该是“哈希冲突”和“空间利用率”矛盾的一个折衷。
跟数据结构要么查询快要么插入快一个道理,hashmap就是一个插入慢、查询快的数据结构。

加载因子是表示Hsah表中元素的填满的程度。
加载因子越大,填满的元素越多,空间利用率越高,但冲突的机会加大了。
反之,加载因子越小,填满的元素越少,冲突的机会减小,但空间浪费多了。

冲突的机会越大,则查找的成本越高。反之,查找的成本越小。

因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡与折衷。

但是为什么一定是0.75?而不是0.8,0.6###

本着不嫌事大的精神继续深挖,在此之前先简单补充点本文需要的基础知识:

1.冲突定义:假设哈希表的地址集为[0,n),冲突是指由关键字得到的哈希地址为j(0<=j<=n-1)的位置上已经有记录。在关键字得到的哈希地址上已经有记录,那么就称之为冲突

2.处理冲突:就是为该关键字的记录扎到另一个**“空”**的哈希地址。即在处理哈希地址的冲突时,若得到的另一个哈希地址H1仍然发生冲突,则再求下一个地址H2,若H2仍然冲突,再求的H3,直至Hk不发生冲突为止,则Hk为记录在表中的地址。

处理冲突的几种方法:#

一、 开放定址法

Hi=(H(key) + di) MOD m i=1,2,…k(k<=m-1)其中H(key)为哈希函数;m为哈希表表长;di为增量序列。

开放定址法根据步长不同可以分为3种:

1**)线性探查法(Linear Probing)**:di=1,2,3,…,m-1
  简单地说就是以当前冲突位置为起点,步长为1循环查找,直到找到一个空的位置就把元素插进去,循环完了都找不到说明容器满了。就像你去一条街上的店里吃饭,问了第一家被告知满座,然后挨着一家家去问是否有位置一样。

2)线性补偿探测法:di=Q 下一个位置满足 Hi=(H(key) + Q) mod m i=1,2,…k(k<=m-1) ,要求 Q 与 m 是互质的,以便能探测到哈希表中的所有单元。
继续用上面的例子,现在你不是挨着一家家去问了,拿出计算器算了一下,然后隔Q家问一次有没有位置。

3)伪随机探测再散列:di=伪随机数序列。还是那个例子,这是完全根据心情去选一家店来问了

缺点:

  • 这种方法建立起来的hash表当冲突多的时候数据容易堆聚在一起,这时候对查找不友好;
  • 删除结点不能简单地将被删结 点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。因此在 用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点
  • 当空间满了,还要建立一个溢出表来存多出来的元素。

二、再哈希法

Hi = RHi(key),i=1,2,…k
RHi均是不同的哈希函数,即在同义词产生地址冲突时计算另一个哈希函数地址,直到不发生冲突为止。这种方法不易产生聚集,但是增加了计算时间。

缺点:增加了计算时间。

三、建立一个公共溢出区

假设哈希函数的值域为[0,m-1],则设向量HashTable[0…m-1]为基本表,每个分量存放一个记录,另设立向量OverTable[0…v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管他们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。

简单地说就是搞个新表存冲突的元素。

四、链地址法(拉链法)

将所有关键字为同义词的记录存储在同一线性链表中,也就是把冲突位置的元素构造成链表。

拉链法的优点:

  • 拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
  • 由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
  • 在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。

拉链法的缺点:

  • 指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度

Java中HashMap的数据结构#

HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

image

看图就可以知道Java中的hashMap使用了拉链法处理冲突。
HashMap有一个初始容量大小,默认是16

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16  

为了减少冲突的概率,当hashMap的数组长度到了一个临界值就会触发扩容,把所有元素rehash再放到扩容后的容器中,这是一个非常耗时的操作。

而这个临界值由【加载因子】和当前容器的容量大小来确定:DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR ,即默认情况下是16x0.75=12时,就会触发扩容操作。

所以使用hash容器时尽量预估自己的数据量来设置初始值。具体代码实现自行去研究HashMap的源码。

基础知识补充完毕,回到正题,为什么加载因子要默认是0.75?
从hashmap源码注释里找到了这一段

Ideally, under random hashCodes, the frequency of

  • nodes in bins follows a Poisson distribution

  • (http://en.wikipedia.org/wiki/Poisson_distribution) with a

  • parameter of about 0.5 on average for the default resizing

  • threshold of 0.75, although with a large variance because of

  • resizing granularity. Ignoring variance, the expected

  • occurrences of list size k are (exp(-0.5) * pow(0.5, k) /

  • factorial(k)). The first values are:

  • 0: 0.60653066

  • 1: 0.30326533

  • 2: 0.07581633

  • 3: 0.01263606

  • 4: 0.00157952

  • 5: 0.00015795

  • 6: 0.00001316

  • 7: 0.00000094

  • 8: 0.00000006

  • more: less than 1 in ten million

注意wiki链接中的关键字:Poisson_distribution
泊淞分布啊

简单翻译一下就是在理想情况下,使用随机哈希码,节点出现的频率在hash桶中遵循泊松分布,同时给出了桶中元素个数和概率的对照表。

从上面的表中可以看到当桶中元素到达8个的时候,概率已经变得非常小,也就是说用0.75作为加载因子,每个碰撞位置的链表长度超过8个是几乎不可能的。

好了,再深挖就要挖到统计学那边去了,就此打住,重申一下使用hash容器请尽量指定初始容量,且是2的幂次方。

关于泊淞分布的知识请看

http://www.ruanyifeng.com/blog/2015/06/poisson-distribution.html#comment-356111

作者:Eric新之助
链接:https://www.jianshu.com/p/dff8f4641814
来源:简书

补充

为什么部位是1或者是0.5

首先说写一下hash的额数据结构,jdk1.8以前是数组+链表,jdk1.8以后是数组+链表+红黑色。

当负载因子是1.0的时候,也就意味着,只有当数组的8个值(这个图表示了8个)全部填充了,才会发生扩容。这就带来了很大的问题,因为Hash冲突时避免不了的。当负载因子是1.0的时候,意味着会出现大量的Hash的冲突,底层的红黑树变得异常复杂。对于查询效率极其不利。这种情况就是牺牲了时间来保证空间的利用率。

负载因子是0.5的时候,这也就意味着,当数组中的元素达到了一半就开始扩容,既然填充的元素少了,Hash冲突也会减少,那么底层的链表长度或者是红黑树的高度就会降低。查询效率就会增加。

image.png

负载因子是0.75的时候,空间利用率比较高,而且避免了相当多的Hash冲突,使得底层的链表或者是红黑树的高度比较低,提升了空间效率。

补充

1、书籍项目:

codeGoogler/ProgramBooks

2:视频教程:

程序员必读Java书籍SpringBoot、Spring、Mybatis、Redis、RabbitMQ、SpringCloud、高并发

觉得不错的小伙伴记得点赞和搜藏哦,后续会持续更新精选技术文章!

为什么HashMap的加载因子是0.75 ? 前言 有很多东西之前在学的时候没怎么注意,笔者也是在重温HashMap的时候发现有很多可以去细究的问题,最终是会回归于数学的,如HashMap的加载因子为什么是0.75? 最近针对互联网公司面试问到的知识点,总结出了Java程序员面试涉及到的绝大部分面试题及答案分享给大家,希望能帮助到你面试前的复习且找到一个好的工作,也节省你在网上搜索资料的时间来学习。 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、 阅读详情

相关推荐

JAVA hashmap 负载因子为什么是0.75,官方解释

java hashmap 扩容因子为什么是0.75,官方给出的解释

为什么java Hashmap 中的加载因子是默认为0.75

前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75。 HashMap源码中的加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f; 当时想到的是应该是“哈希冲突”和“空间利用率”矛盾的一个折衷。 跟数据结构要么查询快要么插入快一个道理,hashmap就是一个插入慢、查询快的数据结构。 加载因子是表示Hs...

没有伞的孩子必须努力奔跑!—小林 1113

【深度学习】tensorboard中的图片放到论文中

1. 利用tensorboard中的导出数据功能 选中左上角的标签,然后选择csv格式的数据下载即可。 左边的smoothing 数值不影响导出数据的大小。 2.tensorboard 图下标签介绍: 放大 Toggle y-axis log scale:将y轴对数化 Fit domain to data:如果拖动了图片等,再重新回到原始位置 Download Current Chart as SVG 3.用下载下来的csv数据来画图 第一幅图片:训练的平均长度 fig, ax1 = plt.sub

gaocui883的博客 1万+

HashMap 扩容阈值为什么是0.75

HashMap 的扩容阈值通常设为 0.75。这是因为,当 HashMap 中的条目数量超过容量的 3/4 时,散列表就可能变得过于稠密,这样就会增加查找的时间复杂度。为了避免这种情况,当 HashMap 的条目数量超过阈值时,它就会触发扩容操作,将容量增加一倍。这样就可以保证 HashMap 中的条目数量不会超过容量的 3/4,从而最大程度地降低查找的时间复杂度。 扩容阈值的具体值并不是固定的,...

weixin_42594419的博客 1449

ENVI遥感技术

记录2024.03.06所遇到的遥感问题

qq_44453923的博客 4330

实测对比:DJI O3、Walksnail Avatar、HDZero三大高清图传,谁才是低延迟王者?

本文对DJI O3、Walksnail Avatar V2和HDZero三大高清图传系统进行了实测对比,重点分析其在FPV飞行中的低延迟表现。通过专业测试环境和量化数据,揭示HDZero在原生低延迟架构上的优势,DJI O3在画质与延迟间的平衡,以及Walksnail的动态码率调整特点,为不同场景下的选购提供决策依据。

weixin_30756499的博客 444

深入理解HashMap加载因子:为什么默认值是0.75?

在Java中,HashMap是一个广泛应用的数据结构,用于存储键值对。HashMap的性能与其内部实现密切相关,其中一个关键参数就是加载因子(load factor)。而常见的默认加载因子值是0.75。在本文中,我们将深入探讨加载因子的作用,为什么选择0.75作为默认值,并通过例子来说明其影响。

qq_28068311的博客 1943

EtherCAT-7 从站代码移植-SPI

STM32F103 + AX58100,从站代码移植。

tianya_xuan的博客 3565

被问懵了:什么是负载因子?为什么是0.75?

前几天面试被问懵了,还是关于 HashMap 的面试题,什么是负载因子?为什么是0.75?第一个问题还好回答,然而第二个问题就有点含糊其辞说不清楚了,所以今天就来好好复盘一下这道题。HashMap 负载因子 load factor,也叫做扩容因子和装载因子,它是 HashMap 在进行扩容时的一个阈值,当 HashMap 中的元素个数超过了容量乘以负载因子时,就会进行扩容。默认的负载因子是 0.75,也就是说当 HashMap 中的元素个数超过了容量的 75% 时,就会进行扩容。

javacn_site的博客 2115

保姆级教程:用CANoe的LIN Slave Conformance Tester搞定一致性测试(附LDF配置避坑点)

本文详细介绍了如何使用CANoe的LIN Slave Conformance Tester进行汽车电子LIN从节点一致性测试,包括测试环境搭建、LDF文件配置、多通道测试技巧及常见问题解决方案。通过实战案例和高级配置技巧,帮助工程师高效完成测试任务,确保LIN总线通信的可靠性。

weixin_30385925的博客 523

软件缺陷(定义+表现形式+优先级+信息+产生原因),看完这篇文章就懂了

软件缺陷软件缺陷的定义软件缺陷的表现形式软件缺陷产生的原因软件缺陷的根源软件缺陷的费用软件缺陷的信息 软件缺陷的定义 IEEE 1983 of IEEE Stardard 729中软件缺陷做了一个标准的定义: 从产品内部看,软件缺陷是软件产品开发或维护过程中所存在的错误、毛病等各种问题;从外部看,软件缺陷是系统所需要实现的某种功能的失效或违背。 因此软件缺陷就是软件产品中所存在的问题,最终表现为用户所需要的功能没有完全实现,没有满足用户的需求。 缺陷不是bug,缺陷包含bug,缺陷的范围更大。 软件缺陷

qq_40676418的博客 1万+

HashMap负载因子为什么是0.75,链表转红黑树阈值为什么是8

1.HashMap负载因子为什么是0.75 这是时间与空间成本上的折中。 1.1时间成本 假设负载因子是1时,虽然空间利用率高了,但是随之提高的是哈希碰撞的概率。 而Hashmap中哈希碰撞的解决方法采用的拉链法,哈希冲突高了会导致链表越来越长(虽然后面会转换成红黑树),我们知道链表的查询效率是比较低的,所以负载因子太高会导致时间成本上升。 1.2空间成本 那么为了减少哈希冲突,提高查询效率,负载因子是不是越低越好呢?答案显然是否定的。 ...

士心的博客 2287

Vivado2022.2下载安装

链接:https://pan.baidu.com/s/1lyfE2d-VmaWC-_aR8ratCQ提取码:mt09。

weixin_61081689的博客 2万+

HashMap的负载因子Load factor为什么默认是0.75?这篇文章告诉你答案---2021-09-10

HashMap的负载因子为什么默认是0.75?这篇文章告诉你答案

Oppuser的博客 662

SpringBoot4.0+JDK25+GraalVM实战:云原生新纪元,微服务性能翻倍的落地指南

三者的组合不是偶然,而是“框架优化+JDK升级+虚拟机革新”的必然结果——SpringBoot4.0完善了对GraalVM原生镜像的支持,JDK25强化了云原生与AOT编译能力,GraalVM则提供了极致的启动速度和资源利用率,三者协同,刚好命中云原生微服务的核心痛点。SpringBoot4.0+JDK25+GraalVM的组合,不是简单的版本升级,而是云原生微服务的一次性能革命。

2601_94871597的博客 1140

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

HashMap的负载因子为什么默认是0.75

负载因子是和扩容机制有关的,意思是如果当前容器的容量,达到了我们设定的最大值,就要开始执行扩容操作。举个例子来解释,避免小白听不懂: 比如说当前的容器容量是16,负载因子是0.75,16*0.75=12,也就是说,当容量达到了12的时候就会进行扩容操作。 他的作用很简单,相当于是一个扩容机制的阈值。当超过了这个阈值,就会触发扩容机制。HashMap源码已经为我们默认指定了负载因子是0.75。 我截取了部分源码,从这里可以看出,系统默认的负载因子值就是0.75,而且我们还可以在构造方...

火麒马 5144

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

HashMap的负载因子初始值为什么是0.75?这篇文章以最通俗的方式告诉你答案

之前写过一篇专门介绍HashMap的文章,反响很不错,不过在留言区问的最多的问题就是HashMap的负载因子初始值为什么是0.75,私下又好好地研究了一番,总结了这篇文章。 本篇文章基于JDK1.8,特在此说明。 OK。下面我们就开始进行分析。 #一、负载因子的作用 对于HashMap的研究,我之前一直停留在考虑源码是如何实现的,现在当我重新再来看的时候,才发现,系统默认的各种参数值,才是Ha...

冯冬冬的博客 1万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

HashMap的负载因子为何默认是0.75

一、负载因子的作用 HashMap负载因子,是和扩容机制有关的,意思是如果当前容器的容量,达到了我们设定的最大值,就要开始执行扩容操作。 举个例子,比如说:当前的容器容量是16,负载因子是0.75,16*0.75=12,也就是说,当容量达到了12的时候就会进行扩容操作。 作用很简单,相当于是一个扩容机制的阈值。当超过了这个阈值,就会触发扩容机制。HashMap源码已经为我们默认指定了负载因子是0.75。 截取部分源码,从这里可以看出,系统默认的负载因子值就是0.75,而且我们还可以在构造方法中.

春风化雨 7355

HashMap的负载因子初始值为什么是0.75?

注:本片文章基于JDK1.8,特在此说明。 一、首先介绍下负载因子的作用 对于HashMap的研究,我之前一直停留在烤炉源码的实现,其实现在看来,系统默认的各种参数才是HashMap的精华所在。 负载因子是和扩容机制有关的,意思时如果当前容器的容量达到了我们设定的最大值,就要开始执行扩容操作。举例说明下 比如说当前的容器容量是16,负载因子是0.75,16*0.75=12,也就是说,当容量达到了1......

damokelisijian866的博客 3693

为什么 HashMap 默认负载因子是0.75?

负载因子 (Load Factor)也叫扩容因子,它是一个用于控制 HashMap 何时进行扩容的参数。当 HashMap 中存储的键值对数量,超过了 HashMap 总容量乘以扩容因子时,HashMap 就会进行扩容操作。例如 HashMap 的总容量为 16,扩容因子为 0.75,那么当 HashMap 中存储的键值对大于 12 (16*0.75)时HashMap 就会进行扩容。注:负载因子的值是 0 到 1 之间 (大于 0,小于 1)。

dream_ready的博客 726

什么是负载因子?为什么是0.75?

HashMap 负载因子 load factor,也叫做扩容因子和装载因子,它是 HashMap 在进行扩容时的一个阈值,当 HashMap 中的元素个数超过了容量乘以负载因子时,就会进行扩容。默认的负载因子是 0.75,也就是说当 HashMap 中的元素个数超过了容量的 75% 时,就会进行扩容。

不定时分享最优质的网络技术与教程,满满的干货。 1296

hashmap负载因子

hashmap负载因子

qq_41583040的博客 2971

为什么HashMap默认负载因子是0.75?——概率统计、时空权衡与工程艺术的完美平衡!

负载因子 = 已存储元素个数 / 哈希表数组长度// 🟡 核心公式 threshold = capacity × loadFactor // 默认:threshold = 16 × 0.75 = 12 // 当 size > 12 时触发扩容序号要点①默认0.75是经过泊松分布推导和实测验证的最优值②一般场景无需修改,直接使用默认值③查询密集场景可调低至0.5-0.6④内存紧张场景可调高至0.8-0.9⑤指定初始容量⑥理解0.75的数学原理,是深入HashMap的关键一步。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 281

为什么HashMap的加载因子是0.75?

目录 HashMap 源码 回答1:jdk1.7代码注释 回答2:jdk1.8代码注释 比较靠谱的回答 总结,我的答案1 二项分布 hashmap的二项分布 我的答案2 总结 引用 HashMap 源码 /** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75)

琦彦 1238

面试官:为什么 HashMap 的默认负载因子要设置成 0.75?

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。基本能保持 O(1)。

weixin_44421461的博客 556
上一篇: 如何设计短网址系统?
下一篇: 大厂用的Hystrix到底有什么优点?
84696zuoguwz
博客等级 码龄5年 12粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值