【Java集合篇】负载因子和容量的关系

在这里插入图片描述

负载因子和容量有什么关系

  • ✔️典型解析
  • ✔️loadfactor为啥默认是0.75F,不是1呢?
    • ✔️为什么HashMap的默认负载因子设置成0.75
      • ✔️0.75的数学依据是什么
      • ✔️0.75的必然因素
  • ✔️HashMap的初始值设为多少合适?


✔️典型解析


HashMap 中有几个属性,如 capacity 记录了 HashMap 中 table 的 length,size记录了HashMap中KV的对数,threshold记录了扩容的阈值 (=loadFactor*capacity) ,loadFactor则是负载因子,一般是3/4。


HashMap 刚刚初始化的时候,如果不指定容量,那么threshold默认是16,如果指定,则默认是第个比指定的容量大的2的幕(如上文所说),此时size=0,capacity=threshold=16loadfactor 默认是0.75F。


HashMap 开始装载的时候 (即调用#put方法),那么size=KV的对数,capacity=16暂时不变,threashold=12 (loadfactor*capacity) ,loadfactor=0.75F


HashMap 中的 size > 12 (threashold) 时,capacity=32 (16 << 1)threashold=24(loadfactor*capacity) , loadfactor=0.75F


由此可得,负载因子决定了什么时候扩容,也间接的决定了HashMap中容量的多少


✔️loadfactor为啥默认是0.75F,不是1呢?


✔️为什么HashMap的默认负载因子设置成0.75


我们知道,当负载因子为1的时候,HashMap就只有当容量满了才会扩容,这样会显得更加节省内存空间,HashMap为什么不这样做呢?


首先,当HashMap完全填满时,发生扩容操作的代价会很高,因为需要重新计算所有键的哈希码并重新分配到新的桶中。这可能导致性能下降。而且,随着HashMap中添加的元素越来越多,哈希冲突的概率会增加,因为元素分布在相对较少的桶中,极端情况下可能会导致某个 Entry 下引用了很长的链表,最终的结果就是虽然节省了空间,但是查询和插入都会很耗时间。


在JDK的官方文档中,有这样一段描述:


As a general rule, the default load factor (.75) offers a good tradeoff between time and
space costs. Higher values decrease the space overhead but increase the lookup cost
(reflected in most of the operations of the HashMap class, including get and put).


翻译过来意思大概就是:


一般来说,默认的负载因子(0.75)在时间和空间成本之间提供了很好的权衡。更高的值减少了空间开销,但增加了查找成本(反映在HashMap类的大多数操作中,包括get和put


✔️0.75的数学依据是什么


另外,我们可以通过一种数学思维来计算下这个值是多少合适。

我们假设一个 bucket 空和非空的概率为0.5,我们用s表示容量,n表示已添加元素个数。


用s表示添加的键的大小和n个键的数目。根据二项式定理,桶为空的概率为:


P(0) = C(n,0) *(1/s)^0 * (1 - 1/s)^(n - 0)


因此,如果桶中元素个数小于以下数值,则桶可能是空的: log(2)/log(s/(s - 1))


当s趋于无穷大时,如果增加的键的数量使P(0) = 0.5,那么n/s很快趋近于log(2) 约等于0.693…所以合理值大概在0.7左右。


当然,这个数学计算方法,并不是在Java的官方文档中体现的,我们也无从考察到底有没有这层考虑这个推测来源于 Stack Overflor


✔️0.75的必然因素


理论上我们认为负载因子不能太大,不然会导致大量的哈希冲突,也不能太小,那样会浪费空间。


通过一个数学推理,测算出这个数值在0.7左右是比较合理的。


🤣那么,为什么最终选定了0.75呢?

答:因为threshold=loadFactor*capacity,并且capacity永远都是2的幂,为了保证负载因子 (loadFactor) * 容量 (capacity) 的结果是一个整数,这个值是0.75(3/4)比较合理,因为这个数和任何2的幂乘积结果都是整数。


✔️HashMap的初始值设为多少合适?


根据阿里巴巴Java开发手册的描述来看:


在这里插入图片描述


假如说我们预期的Map中的值为16个,那么我们不能直接使用 new HashMap<>(16),因为HashMap会在size>12的时候开始扩容,所以合理的方式应该是使用 new HashMap<>(16*4/3+1)才对,这种计算对于开发者来说,显然会复杂一点,所以推荐使用Guava提供的集合工具类,其源码如下:


public static <K,V> HashMap<KV> newHashMapwithExpectedSize(int expectedsize) {
	return new HashMap<KV>(capacity(expectedsize));
}

/**
*  Returns a capacity that is sufficient to keep the map from being resized as long as it grows no
* larger than expectedsize and the load factor is > its default (0.75).
*/
static int capacity(int expectedsize) {
	if (expectedsize < 3) {
		checkNonnegative(expectedsize,"expectedsize");
		return expectedsize + 1;
	}
	if (expectedsize < Ints.MAX_POWER_OF_TWO) {
		// This is the calculation used in JDK8 to resize when a putAll
		// happens; it seems to be the most conservative calculation we
		//can make,  0.75 is the default load factor.
		return (int) ((float) expectedsize / 0.75F + 1.0F);
	}
	return Integer.MAX_VALUE; // any large value
}

不过很多时候,我们其实需要的是一些不可变的Map,可以直接使用Guava提供的不可变集合,就没有上面所说的一些问题了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/297849.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

商智C店H5性能优化实战

前言 商智C店&#xff0c;是依托移动低码能力搭建的一个应用&#xff0c;产品面向B端商家。随着应用体量持续增大&#xff0c;考虑产品定位及用户体验&#xff0c;我们针对性能较差页面做了一次优化&#xff0c;并取得了不错的效果&#xff0c;用户体验值&#xff08;UEI&…

每日一题——LeetCode1089.复写0

方法一 splice&#xff1a; 通过数组的slice方法&#xff0c;碰到 0就在后面加一个0&#xff0c;最后截取原数组的长度&#xff0c;舍弃后面部分。 但这样做是违反了题目的要求&#xff0c;不要在超过该数组长度的位置写入元素。 var duplicateZeros function(arr) {var le…

docker 完成MySQL的主从复制

文章目录 搭建步骤 搭建步骤 拉取镜像 docker pull mysql:5.7运行主从 docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_P…

Springboot进行多环境配置的2种方式

本文来说下Springboot使用Spring Profile和Maven Profile进行多环境配置 文章目录 概述Spring Profile多环境主配置文件与不同环境的配置文件 Maven ProfileProfile配置资源过滤 Spring Profile与Maven Profile具体使用 概述 原因 在实际的项目上&#xff0c;一般会分三种环境d…

淘宝商品详情API接口(item_get-获得淘宝商品详情)主图,属性,sku,价格,搜索商品列表

淘宝开放平台提供了API接口&#xff0c;允许开发者获取淘宝商品的相关信息。为了获取商品详情&#xff0c;您可以使用 item_get API接口。以下是如何使用此API接口来获取商品的主图、属性、SKU、价格以及搜索商品列表的简要说明&#xff1a; 公共参数 名称类型必须描述keyStr…

如何利用MiniTab的命令行来提高数据建模效率

使用MiniTab进行数据建模时&#xff0c;如果涉及到需要多次更改数据、多次查看模型&#xff0c;感兴趣的同学可以尝试一下&#xff0c;把命令行显示出来&#xff0c;通过命令行的形式来执行&#xff0c;避免在繁多的菜单中到处查找。 操作方式如下图&#xff1a; 点击菜单“查…

Transformer架构和对照代码详解

1、英文架构图 下面图中展示了Transformer的英文架构&#xff0c;英文架构中的模块名称和具体代码一一对应&#xff0c;方便大家对照代码、理解和使用。 2、编码器 2.1 编码器介绍 从宏观⻆度来看&#xff0c;Transformer的编码器是由多个相同的层叠加⽽ 成的&#xff0c;每个…

Java重修第三天—“方法“的案例练习

案例一&#xff1a;买飞机票 题目 用户购买机票时&#xff0c;机票原价会按照淡季、旺季&#xff0c;头等舱还是经济舱的情况进行相应的优惠&#xff0c;优惠方案如下:5-10月为旺季&#xff0c;头等舱9折&#xff0c;经济舱8.5折。11月到来年4月为淡季&#xff0c;头等舱7折&…

内核线程创建-kthread_create

文章参考Linux内核线程kernel thread详解 - 知乎 大概意思就是早期创建内核线程&#xff0c;是交由内核处理&#xff0c;由内核自己完成&#xff08;感觉好像也不太对呢&#xff09;&#xff0c;创建一个内核线程比较麻烦&#xff0c;会导致内核阻塞。因此就诞生了工作队列以及…

美格智能5G RedCap模组SRM813Q通过广东联通5G创新实验室测试认证

近日&#xff0c;美格智能5G RedCap轻量化模组SRM813Q正式通过广东联通5G创新实验室端到端的测试验收&#xff0c;获颁测评证书。美格智能已连续通过业内两家权威实验室的测试认证&#xff0c;充分验证SRM813Q系列模组已经具备了成熟的商用能力&#xff0c;将为智慧工业、安防监…

docker - 常用容器部署命令大全(MySQL、Redis、RabbitMQ、ES、Kibana、Nacos、Sentinel)

目录 一、常用容器运行指令 MySQL Redis RabbitMQ ElasticSearch & kibana Nacos Sentinel 一、常用容器运行指令 MySQL docker run -d --name mysql -p 3306:3306 -e TZAsia/Shanghai -e MYSQL_ROOT_PASSWORD1111 mysql:5.7 -e TZAsia/Shanghai&#xff1a;指定…

听GPT 讲Rust源代码--compiler(26)

File: rust/compiler/rustc_target/src/abi/call/mips.rs 在Rust源代码中的rust/compiler/rustc_target/src/abi/call/mips.rs文件是关于MIPS架构的函数调用ABI(Aplication Binary Interface)定义。ABI是编程语言与底层平台之间的接口规范&#xff0c;用于定义函数调用、参数传…

centos7部署minio单机版

一、目标 在centos7上部署minio单机版 二、centos7部署minio 1、下载minio mkdir /usr/local/minio cd /usr/local/minio wget https://dl.minio.io/server/minio/release/linux-amd64/minio chmod x minio 2、新建minio存储数据的目录 mkdir -p /data/minio/data3、新建…

首次引入大模型!Bert-vits2-Extra中文特化版40秒素材复刻巫师3叶奈法

Bert-vits2项目又更新了&#xff0c;更新了一个新的分支&#xff1a;中文特化&#xff0c;所谓中文特化&#xff0c;即针对中文音色的特殊优化版本&#xff0c;纯中文底模效果百尺竿头更进一步&#xff0c;同时首次引入了大模型&#xff0c;使用国产IDEA-CCNL/Erlangshen-Megat…

外包干了1个月,技术退步一大半。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

FFmpeg读取Assets资源文件

在Android开发中我们经常把原生资源文件放在assets目录下以供需要时读取&#xff0c;通过API提供的resources.assets.open(filename)/openFd(filenam)方法可以非常方便获得InputStream或FileDescriptor&#xff08;文件标识符&#xff09;&#xff0c;但是在使用FFmpeg读取Asse…

Keil使用手册

文章目录 1 设置1.1 背景1.2 Project窗口显示.h文件1.3 注释1.4 Project窗口消失TAB转空格的设置keilsourceInsight 显示cannot evaluate普通局部变量静态全局变量静态局部变量 2 报错与解决2.1 warning&#xff1a;#1-D last line of file ends without anewline2.2 中文乱码 …

13. 强化学习编程实验1-在格子世界中寻宝(1)

文章目录 1.实验目的2.任务描述3.任务分析3.1 待求问题是多步决策问题否3.2 问题求解过程是一个马尔科夫决策过程3.3 状态空间S的确定3.4 动作空间A的确定3.5 状态转移概率P的确定3.6 立即回报R的确定3.7 折扣 γ \gamma γ的确定 4. 编程架构4.1 程序中有哪些对象和类4.2 环境…

Python中的@abstractmethod

abstractmethod 是 Python 中 abc 模块&#xff08;Abstract Base Classes&#xff09;提供的一个装饰器&#xff0c;用于声明抽象方法。抽象方法是指在抽象类中声明但没有提供具体实现的方法&#xff0c;而是由其子类提供具体实现。 使用 abstractmethod 装饰器可以使得子类在…