java hashmap扩容大小_HashMap 扩容机制

java hashmap扩容大小_HashMap 扩容机制HashMap:publicHashMap(intinitialCapacity,floatloadFactor){//初始容量不能<0if(initialCapacity<0)thrownewIllegalArgumentException(“Illegalinitialcapacity:”+initialCapacity)…

大家好,又见面了,我是你们的朋友全栈君。

HashMap:

48304ba5e6f9fe08f3fa1abda7d326ab.png

public HashMap(int initialCapacity, floatloadFactor) {

//初始容量不能<0

if (initialCapacity < 0)throw new IllegalArgumentException(“Illegal initial capacity: ” +initialCapacity);

//初始容量不能 > 最大容量值,HashMap的最大容量值为2^30

if (initialCapacity >MAXIMUM_CAPACITY)

initialCapacity=MAXIMUM_CAPACITY;//负载因子不能 < 0

if (loadFactor <= 0 ||Float.isNaN(loadFactor))

throw new IllegalArgumentException(“Illegal load factor: ” +loadFactor);

//计算出大于 initialCapacity 的最小的 2 的 n 次方值。

int capacity = 1;

while (capacity

capacity<<= 1;this.loadFactor =loadFactor;

//设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行扩容操作

threshold = (int) (capacity *loadFactor);//初始化table数组

table = newEntry[capacity]; init();

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

在这里提到了两个参数:初始容量,加载因子。

这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,

加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。

对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;

如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。系统默认负载因子为0.75,一般情况下我们是无需修改的。

加载因子:

loadFactor

扩容:

48304ba5e6f9fe08f3fa1abda7d326ab.png

void addEntry(int hash, K key, V value, intbucketIndex) {

Entry e =table[bucketIndex];

table[bucketIndex]= new Entry(hash, key, value, e);

if (size++ >= threshold) //这里是关键,一旦大于等于threshold的数值

resize(2 * table.length); //将会引起容量2倍的扩大

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

void resize(intnewCapacity) {

Entry[] oldTable=table;

int oldCapacity =oldTable.length;

if (oldCapacity ==MAXIMUM_CAPACITY) {

threshold=Integer.MAX_VALUE;return;

}

Entry[] newTable= new Entry[newCapacity]; //新的容器空间

transfer(newTable); //复制数据过去

table =newTable;

threshold= (int)(newCapacity * loadFactor); //重新计算threshold的值

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

voidtransfer(Entry[] newTable) {//保留原数组的引用到src中,

Entry[] src =table;//新容量使新数组的长度

int newCapacity =newTable.length;

//遍历原数组

for (int j = 0; j < src.length; j++) {

//获取元素e

Entry e =src[j];if (e != null) {//将原数组中的元素置为null

src[j] = null;

//遍历原数组中j位置指向的链表

do{

Entry next =e.next;//根据新的容量计算e在新数组中的位置

int i =indexFor(e.hash, newCapacity);//将e插入到newTable[i]指向的链表的头部

e.next =newTable[i];

newTable[i]=e;

e=next;

}while (e != null);

}

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

通过上面的transfer方法可以看出,

e.next=newTable[i];

newTable[i]=e;

链表存储倒过来了,最先出来的会将其next指向null,后面的就指向前一个,当然数据只有原来的一部分。

===================================================================

随着HashMap中元素的数量越来越多,发生碰撞的概率就越来越大,所产生的链表长度就会越来越长,这样势必会影响HashMap的速度,

为了保证HashMap的效率,系统必须要在某个临界点进行扩容处理。

该临界点在当HashMap中元素的数量等于table数组长度*加载因子。

但是扩容是一个非常耗时的过程,因为它需要重新计算这些数据在新table数组中的位置并进行复制处理。

所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

问题:

当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。

在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。

如果条件竞争发生了,那么就死循环了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149916.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • wireshark抓包分析TCP和UDP_ipv4数据包分析

    wireshark抓包分析TCP和UDP_ipv4数据包分析在命令行输入ifconfig,查看本机网络接口。$ifconfigenp4s0:flags=4099<UP,BROADCAST,MULTICAST>mtu1500etherc8:5b:76:f6:44:d2txqueuelen1000(Ethernet)RXpackets0bytes0(0.0B)…

    2025年7月3日
    4
  • iOS 中 Touch ID得使用方法「建议收藏」

    iOS 中 Touch ID得使用方法

    2022年1月27日
    47
  • 四旋翼飞行器1——结构和控制原理

    四轴飞行器是一个在空间具有6个活动自由度(分别沿3个坐标轴作平移和旋转动作),但是只有4个控制自由度(四个电机的转速)的系统,因此被称为欠驱动系统(只有当控制自由度等于活动自由度的时候才是完整驱动系统)四旋翼飞行器的结构可大致分为两种结构形式:“十字形”结构该种结构四个旋翼对称分布在机体的前后、左右方向,四个旋翼处于同一高度平面,且四个旋翼的结构和半径都相同,四个电机对称的安装在飞行器的支…

    2022年4月8日
    80
  • pycharm2021激活码【中文破解版】

    (pycharm2021激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~9ADCNKZL59-eyJsaWNlb…

    2022年3月22日
    79
  • CUDA编程(机械编程)

    CUDA编程——简介参考了很多大神的内容,并非完全原创,只是为了查漏补缺,记录自己的学习过程。个人水平有限,错误难免,欢迎讨论。

    2022年4月17日
    46
  • 经典手眼标定算法之Tsai-Lenz的OpenCV实现

    经典手眼标定算法之Tsai-Lenz的OpenCV实现本文主要是讲解经典手眼标定问题中的TSAI-LENZ文献方法,参考文献为“ANewTechniqueforFullyAutonomousandEfficient3DRoboticsHand/EyeCalibration”,并且实现了基于OpenCV的C++代码程序,code可去CSDN资源下载。

    2022年6月11日
    34

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号