1. 为啥需要 负载因子(defaultLoadFactor)

现在主流的 HashMap,一般的实现思路都是开放地址法+链地址法的方式来实现。

即数组 + 链表的实现方式,通过计算哈希值,找到数组对应的位置,如果已存在元素,就加到这个位置的链表上。在 Java 8 之后,链表过长还会转化为红黑树。红黑树相较于原来的链表,多占用了一倍的空间,但是查询速度快乐一个数量级,属于空间换时间。 同时,链表转换红黑树也是一个耗时的操作。并且,一个效率高的哈希表,这个链表不应该过长

所以,如果数组的很多元素上面已经有值了,那么就需要将这个数组扩充下,重建哈希表,也就是 rehash,因此这个 rehash 相当耗时。那么什么时候扩容呢?

**当数组填满的时候?**那么在数组快要填满的时候,会发生很多需要将元素加到对应位置的链表上的情况,并且增加产生红黑树的概率。这显然不可取。

这个 defaultLoadFactor 就是一个比较合适的,哈希表需要扩容的时候的 数组中有占用元素的比例

2. 这个比例如何计算?

其实,这个并没有一个统一的结论,因为不同场景下,肯定考虑的方面不同,这个数字最好能最通用。但是,目前不同语言的 defaultLoadFactor 并不一样,比如 Java 是 0.75,Go 中是 0.65,Dart 中是0.8,python 中是0.762.

这里参考(https://stackoverflow.com/questions/10901752/what-is-the-significance-of-load-factor-in-hashmap/31401836#31401836)的思路,说一种推导方式:

首先,这个基于一个假设,那么就是当一个事件发生的概率大于 0.5,那么这件事就是很可能发生的。

然后,假设当前有 s 个桶,那么每次放入一个元素进入某一个桶的概率就是:

放入了第 n 个元素,那么,某一个桶元素个数为e的概率,根据二项式分布就是:

将e=0代入,得出:

让这个概率 大于 0.5 也就是 1/2

那么解这个不等式,得到:

如果让 s 趋近于无穷大,那么 n/s 就无限接近于 log(2). 也就是放入的元素数量是所有桶的数量的 log(2) ~ 0.693

3. 为何 Java 8 中的红黑树是链表大于8的时候转换

这个是在 defaultLoadFactor = 0.75 的基础上,根据泊松分布概率计算得出的结论。我们要保证,这个界限,不能太大,否则遇到链表确实比较长的时候,查询效率低。更不能太小,否则转换的性能损耗还有空间占用大。所以,我们期望,每个桶上面元素个数超过 k 的概率尽量小,并且这个 k 不算很大,就可以了。

首先,对于任意一个 HashMap 的数组上面的元素,存入一个数据,要么放入要么不放入,概率分别是 50%,期望 E 是 0.5. 泊松分布是二项分布的极限形式,就是有且只有两个相互对立的结果的概率分布,对于这个位置上面链表元素个数为 k ,其概率公式是:

期望 E = 0.5,代入,对于 k=1 到 8 的情况,概率分别是:

0: 0.606530661: 0.303265332: 0.075816333: 0.012636064: 0.001579525: 0.000157956: 0.000013167: 0.000000948: 0.00000006

k=8 时,概率足够小,所以采用 8 作为变成红黑树的界限。

每日一面 - 为何hashmap默认的负载因子是0.75?应该是空间和时间的折中,背后的统计原理是什么呢?相关推荐

  1. [转]为什么Java中的HashMap默认加载因子是0.75

    前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75. HashMap源码中的加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75 ...

  2. 【java】为什么 HashMap 的加载因子是0.75?

    1.概述 转载:为什么 HashMap 的加载因子是0.75? 有很多东西之前在学的时候没怎么注意,笔者也是在重温HashMap的时候发现有很多可以去细究的问题,最终是会回归于数学的,如HashMap ...

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

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://blog.csdn.net/N ...

  4. eui加载时间长_面试官:为什么 HashMap 的加载因子是0.75?

    有很多东西之前在学的时候没怎么注意,笔者也是在重温HashMap的时候发现有很多可以去细究的问题,最终是会回归于数学的,如HashMap的加载因子为什么是0.75? 本文主要对以下内容进行介绍: 为什 ...

  5. 面试官:为什么 HashMap 的加载因子是0.75?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 来源:8rr.co/8V9Q 有很多东西之前在学的时候没怎么注意, ...

  6. 为什么 HashMap 默认加载因子非得是0.75?

    点击上方 "编程技术圈"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 每日英文 Sometimes,God does not give you w ...

  7. 转载和积累系列 - 为什么 HashMap 加载因子是0.75?而不是0.8,0.6?

    目录 为什么HashMap需要加载因子? 解决冲突有什么方法? 1. 开放定址法 2. 再哈希法 3. 建立一个公共溢出区 4. 链地址法(拉链法) 为什么HashMap加载因子一定是0.75?而不是 ...

  8. element 往node里面增加属性值_HashMap加载因子为何0.75,为何初始化值2的指数幂,底层解析...

    01 前言 我们在声名HashMap的时候,一般都会这样写. public class MapTest { public static void main(String[] args) { HashM ...

  9. hashmap 不释放空间_刁难问题,为什么HashMap默认容量为16加载因子为0.75

    前言:实际开发中我们大多数都是只能new HashMap<>来存储键值对,很少会去设置初始容量,虽然我们知道他的默认容量是16.但是在面试中,为了体现你个人好学的能力,还是会被经常问到为什 ...

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

    作用 负载因子是和扩容机制有关的,意思是如果当前容器的容量,达到了我们设定的最大值,就要开始执行扩容操作.比如说当前的容器容量是16,负载因子是0.75,16*0.75=12,也就是说,当容量达到了1 ...

最新文章

  1. 逆向知识十三讲,汇编中数组的表现形式,以及还原数组
  2. unsigned int mysql_mysql 中int类型字段unsigned和signed的探索
  3. 爬虫那些事儿-- 简介
  4. 微众银行软件测试笔试题,微众银行4月8日笔试题目及部分代码
  5. centos安装python gcc sqlite
  6. 简单工厂模式和策略模式结合使用php
  7. DeFi衍生品协议dFuture未来5日将通过公测奖励100万枚DFT
  8. Acrobat Pro DC 2021 for Mac(pdf编辑器)中文版
  9. 拓端tecdat|Matlab建立SVM,KNN和朴素贝叶斯模型分类绘制ROC曲线
  10. 微信小程序模仿购物车页面
  11. .NET 将PDF转成图片之Magick.NET(亲测可用)
  12. USBCAN卡解决新能源汽车CAN总线测试问题
  13. 内存空间的分配与回收
  14. threejs 特效 自定义发光围栏,发光墙体,闪烁动画
  15. linux 解压zip文件到指定文件夹,Linux解压文件到指定目录
  16. java中driver是什么意思_java.sql.SQLException: com.sqljdbc.Driver什么意思啊?
  17. Unity3d Ugui 10 Toggle ToggleGroup
  18. DNSPod十问深创投刘辉:产业互联网是烧钱做慈善吗?
  19. 聊天机器人:问答系统类型介绍
  20. 小众“上位”!双目立体视觉+激光雷达,奔驰从S级“玩到”C级

热门文章

  1. 陈式太极拳式名考释、动作、着法要领说明
  2. 自己写的随手记事程序
  3. Google Guava简介
  4. 人工智能区块链智能合约_通过业务规则使您的区块链智能合约更智能
  5. web(Response、ServletContext)
  6. [CGAL]建立一个正四面体
  7. 台式计算机usb口不能用,电脑USB接口没反应如何解决教程
  8. ArcGIS Server 发布地图服务遇到的问题
  9. Android最新API获取北斗卫星定位信息(全网最新)
  10. 微信小程序自定义组件(1)----地址选择器