Java集合:HashMap

本文详细介绍了Java中的HashMap数据结构及其工作原理。HashMap提供快速的索引和查找,插入与删除操作时间复杂度均为O(1)。它通过key的hashcode存储在数组中,使用链表处理冲突,当链表过长时转换为红黑树以提升查询效率。HashMap在负载因子达到0.75时会扩容,确保性能。此外,还讨论了hash值的计算策略,以减少冲突并充分利用hashcode。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java集合:HashMap

Hashmap是一个存储key-value的映射表。

优点:

索引数据快,查找一个数据对的时间复杂度是O(1)
增加、删除一个数据的时间复杂度是O(1)
key不能重复,可以存储一个null值

存储:
通过key的hashcode值存储在指定数组下标中
用链表存储hashcode值一样,都是key不一样的数据,链表长度大于8时转换为红黑树(为了提高查询效率)
HashMap的内部结构
Hashmap封装了一个Node数组进行存储key-value的键值对,常用的get和put等都是对这个Node数组进行操作。

Node有四个属性:key、value、hash、next

hash:32位的整数,通过key的hashcode计算出来,hash&(数组长度-1) = 元素在数组的下标
next:指向Node节点的指针,不同的key计算出来的hash值可能是一样的,如果要存储的下标位置已经有值了,用链表将元素连起来
初始化HashMap:一开始HashMap内部是一个空的Node数组,插入数据后才会被创建

HashMap的常用操作
HashMap一开始的Node数组是空的,在第一次put元素后会默认创建一个长度为n = 16的数组

put一个key-value元素进入map中
计算key的hashcode值算出hash,得出index=hash&(长度-1),将元素存在数组[index]的位置。

有两种情况:

index这个位置已经有key了,比如当数组的长度是16时,33&(16-1) = 1. , 1 & (16 - 1) = 1 ; key值不同,但是index一样。

这里就用到了Node的next属性,让数组index下标所在的(最后一个)元素的next指向插入的元素,

可以直接将元素存入数组中
通过key从map中get一个元素
计算key的hashcode值算出hash,得出index=hash&(长度-1)

有两种情况:

如果数组[index]的值为null,就说明不存在这个元素
不为null,还得比较key值,通过遍历链表(如果有的话),一个个比较key值,返回key相同的元素,或null

HashMap的优化操作
数组长度n永远是2的幂:hash&(n-1)是元素在数组的下标,(2的幂-1)的二进制会是一连串的1,然后与hash值进行与运算
与运算之后的结果永远不会超过数组的界限
充分的利用了hash值二进制

负载因子:hashmap设置了一个0.75的阈值,也就是数组中的元素数量大于数组长度的0.75时,进行数组扩容,扩展成原来的两倍
当数组长度不够时,会出现很多的hash冲突,就是链表很长,检索效率慢,扩容后通过hash&(n-1)会让很长的链表散开

链表转换成红黑树:链表长度大于8,但是数组元素数量没达到阈值,会选择将链表转换为红黑树,提高查询效率
要求数组长度已经大于64,避免数组扩容和链表转红黑树的冲突

hash值的计算:hash值的前16位与key的hashcode一样,后16位由hashcode的前16位与后16位异或运算得到
充分利用hashcode的值,增加随机性,减少hash冲突

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值