【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提供的不可变集合,就没有上面所说的一些问题了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS ArkTS 三方库的基本使用(十六)

如何获取三方库 目前提供了两种途径获取开源三方库&#xff1a; 1、通过访问Gitee网站开源社区获取 在Gitee中&#xff0c;搜索OpenHarmony-TPC仓库&#xff0c;在tpc_resource中对三方库进行了资源汇总&#xff0c;可以供开发者参考。 2、通过OpenHarmony三方库中心仓获取 …

【已解决】js定义对象属性是.如何访问

当变量没有length属性的时候&#xff0c;可能是个对象变量&#xff0c;当有键值对的时候就可能是个对象&#xff0c;读者都知道的是&#xff0c;用typeof(变量)可以查看属性&#xff0c;今天本文解决的问题是如果js定义对象中属性是"点"如何访问 问题再现 var a {…

C语言习题集(035)

//有n个人围成一圈&#xff0c;顺序排号。从第1个人开始报 //数&#xff08;从1到3报数&#xff09;&#xff0c;凡报到3的人退出圈子&#xff0c;问 //最后留下的是原来第几号的那位。 /* */ //解答&#xff1a; #include<stdio.h> int main() { int a[10000],n,i,k0,…

谈谈我的三次考研经历

阿七经历过三次考研。 第一次&#xff0c;大四毕业那年&#xff0c;大三开始有紧迫感&#xff0c;因为大学几年什么也没学会&#xff0c;毕业考试成绩从第二个学期开始就一路下滑&#xff0c;每次都是考前一周突击&#xff0c;最后擦着及格线通过。 大三就开始和几个同学组队…

iPhone 恢复出厂设置后如何恢复数据

如果您在 iPhone 上执行了恢复出厂设置&#xff0c;您会发现所有旧数据都被清除了。这对于清理混乱和提高设备性能非常有用&#xff0c;但如果您忘记保存重要文件&#xff0c;那就是坏消息了。 恢复出厂设置后可以恢复数据吗&#xff1f;是的&#xff01;幸运的是&#xff0c;…

第13课 利用openCV检测物体是否运动了

FFmpeg与openCV绝对是绝配。前面我们已经基本熟悉了FFmpeg的工作流程&#xff0c;这一章我们重点来看看openCV。 在前面&#xff0c;我们已经使用openCV打开过摄像头并在MFC中显示图像&#xff0c;但openCV能做的要远超你的想像&#xff0c;比如可以用它来实现人脸检测、车牌识…

基于平衡优化器算法优化的Elman神经网络数据预测 - 附代码

基于平衡优化器算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于平衡优化器算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于平衡优化器优化的Elman网络5.测试结果6.参考文献7.Matlab代码…

vivado xsim 终端 模拟

只模拟的话直接终端运行会快很多 计数器举例 mkdir srccounter.v module counter(input wire clk,input wire rst_n,output reg[31:0] cnt ); always (posedge clk or negedge rst_n)if(!rst_n)cnt < 31h0;elsecnt < cnt1;endmodule tb.v module tb; wire[31:0] out…

【大厂秘籍】系列 - Java多线程面试题

Java多线程面试题 友情提示&#xff0c;看完此文&#xff0c;在Java多线程这块&#xff0c;基本上可以吊打面试官了 线程和进程的区别 进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 线程是进程的子集&#xff0c;一个进程可以有很多线程&#xff0c;每条线…

【复现】DiffTalk

code&#xff1a;GitHub - sstzal/DiffTalk: [CVPR2023] The implementation for "DiffTalk: Crafting Diffusion Models for Generalized Audio-Driven Portraits Animation" 问题1. ERROR: Failed building wheel for pysptk Cython.Compiler.Errors.CompileError:…

Beauty algorithm(三)腮红

查阅资料了解到腮红位于苹果肌处,同样使用关键点确定目标区域,然后对该区域进行渲染达到美妆效果。考虑到如果使用简单的RGB是很难做到特效,本篇采用模板方式进行区域融合。 一、skills 前瞻 1、png图像读取 cv::imread(imgPath, cv::IMREAD_UNCHANGED) IMREAD_UNCHANGE…

python属性管理getattr、getattribute、setattr和delattr避免循环

1 python属性管理getattr、getattribute、setattr和delattr避免循环 在__getattr__()、__getattribute__()和__setattr__()方法体内&#xff0c;通过self进行对应的点号运算、赋值运算&#xff0c;会自动调用当前实例的相应方法&#xff0c;导致无限循环。通过object或者__dic…

小红书 X WSDM 2024「对话式多文档问答挑战赛」火热开赛!

基于大语言模型&#xff08;LLM&#xff09;的对话问答机器人&#xff0c;已经成为当前人工智能领域学术界和工业界共同关注的的热门研究方向之一。在对话过程中&#xff0c;为大模型引入搜索结果&#xff0c;进行检索增强的生成&#xff08;Retrieval Augmented Generation&am…

MyBatis-Plus实现自定义SQL语句的分页查询

正常开发的时候&#xff0c;有时候要写一个多表查询&#xff0c;然后多表查询之后还需要分页&#xff0c;MyBatis-Plus的分页插件功能挺不错的&#xff0c;可以很简单实现自定义SQL的分页查询。 分页插件配置 import com.baomidou.mybatisplus.annotation.DbType; import com…

深度解析Webpack:现代前端工程化的利器

引言&#xff1a; 前端工程化是当今前端开发的不可或缺的一部分&#xff0c;而Webpack作为其中的瑞士军刀&#xff0c;在项目构建和优化中扮演着至关重要的角色。本文将深度解析Webpack&#xff0c;从基础概念到实际应用&#xff0c;为前端开发者提供全面的学习指南&#xff0…

MyBatis自定义类型处理器 TypeHandler(通俗易懂,效率起飞),处理jsonb、数组、枚举类型。支持MybatisPlus

一 使用场景 在项目开发过程中&#xff0c;我们经常遇到这样的情况&#xff1a;Java 对象中的数据类型与数据库中的字段类型不一致。这时&#xff0c;我们需要在保存数据到数据库和从数据库检索数据时进行类型转换。例如&#xff1a; 对于一些数据库特有的数据类型&#xff0…

Go语言并发模式视角思考

犹记得2019年中旬进行知识点的学习和demo的练习&#xff0c;熟悉各种语法和并发调度的场景&#xff0c; 在2019年末开始参与项目实战开发和逻辑梳理 Go语言的接触也是更多探索和业务的拆件&#xff0c;做一些雏形工具&#xff0c;来慢慢的孵化业务生态 后来陆陆续续&#xff…

时间序列预测 — LSTM实现多变量多步负荷预测(Tensorflow):多输入多输出

目录 1 数据处理 1.1 导入库文件 1.2 导入数据集 ​1.3 缺失值分析 2 构造训练数据 3 LSTM模型训练 4 LSTM模型预测 4.1 分量预测 4.2 可视化 1 数据处理 1.1 导入库文件 import time import datetime import pandas as pd import numpy as np import matplotlib.p…

软件测试|教你如何使用UPDATE修改数据

简介 在SQL&#xff08;Structured Query Language&#xff09;中&#xff0c;UPDATE语句用于修改数据库表中的数据。通过UPDATE语句&#xff0c;我们可以更新表中的特定记录或多条记录&#xff0c;从而实现数据的修改和更新。本文将详细介绍SQL UPDATE语句的语法、用法以及一…

【AI视野·今日Robot 机器人论文速览 第六十七期】Mon, 1 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Mon, 1 Jan 2024 Totally 16 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers MURP: Multi-Agent Ultra-Wideband Relative Pose Estimation with Constrained Communications in 3D Environments Authors A…