关注
提问:hashmap什么时候会触发扩容? 回答:两种情况(基于JDK1.8) 1. 当HashMap中元素总个数达到阈值时就会扩容。注意是元素总个数,而不是数组占用个数。 // 数组扩容阈值,即:HashMap数组总容量 * 负载因子
int threshold
// 如果元素个数大于阈值,扩充数组。
if (++size > threshold)
resize(); 2. 比较复杂,当向HashMap中添加元素时,即调用 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) 方法时,如果通过hash值计算数组的索引,获取该索引位的首节点,且该首节点不为null时(即发生了Hash碰撞),会有对应三种处理情况: ① 新添加元素的key与首节点元素的key相同,即 // 如果首节点的key和要存入的key相同,那么直接覆盖value的值。
// p:hash值对应索引位置的首节点
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
e = p; ② 如果首节点是红黑树节点(TreeNode),将键值对添加到红黑树。 // 如果首节点是红黑树的,将键值对插添加到红黑树
else if (p instanceof HashMap.TreeNode)
e = ((HashMap.TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); ③ 如果首节点是链表,将键值对添加到链表。添加之后会判断链表长度是否到达TREEIFY_THRESHOLD - 1这个阈值,“尝试”将链表转换成红黑树。 // p.next == null,到达链表末尾,添加新节点,如果长度足够,转换成树结构。
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
} 而关键在于这个treeifyBin()方法中,如果 // 把链表转换为红黑色
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e; // 如果当前数组容量太小(小于64),放弃转换,扩充数组。
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) {
resize();
} else if ((e = tab[index = (n - 1) & hash]) != null) {
// 将链表转成红黑树...
}
} HashMap在jdk1.8之后引入了红黑树的概念,表示若桶中链表元素超过8时,会自动转化成红黑树;若桶中元素小于等于6时,树结构还原成链表形式。而如果当前数组的容量太小(小于64),则放弃转换,扩充数组。扩充数组!扩充数组!扩充数组! 这样就有可能有一种情况出现,就是说我整个HashMap并没有达到负载因子那么多的元素个数,但是,我进行了一次扩容。所以单纯的以负载因子来看是否会发生扩容,是不全面的。 那我们来分析为什么要进行这一次扩容。 首先我们要理解HashMap为什么要进行扩容,扩容这个操作真正的意义在哪里?为什么要定义一个负载因子?设计他的初衷究竟是为了解决什么问题? 为什么要扩容呢,之所以要扩容,我理解是基于两个逻辑, 1. HashMap中元素个数实在太多了,已经很频繁的发生hash冲突,我不得不进行扩容来减少这个冲突,来增强效率。 2. HashMap中元素并不多,但元素都集中到那么一两个“坑位”上,数组占用的位置很少,但是在那一两个位置上的元素已经很多了,拖掉了执行的效率。即核心是一个分布不均匀的问题,在这样的情况下,扩容的目的,就是通过重新计算hash“坑位”让原来聚集在一起的节点分散开来,是为了让分布更加均匀。 而treeifyBin()方法中,之所以判断当前数组容量是否太小,也是基于第二个逻辑上的考量,因为数组容量很小,但是已经存在过长的链表需要转换成树结构,不如直接进行一次扩容,毕竟树的查询效率O(logn)也比不上一个正常HashMap的O(1)的效率。
查看原帖
8 2
相关推荐
08-26 15:11
凯里学院 硬件测试 点赞 评论 收藏
分享
点赞 评论 收藏
分享
牛客热帖
更多
- 1... 26国考公告出炉,放宽到38岁意味着什么5414
- 2... 《从研一摆烂到稳拿oc:嵌入式er的踩坑血泪史,这些弯路真的别再走了!》4815
- 3... 害,找工作哪有不上当的!4454
- 4... 京东官宣发布新车,会有新的HC吗?3465
- 5... 牛牛求救🆘,不敢梭哈后端第二技能点怎么搭配3109
- 6... 下一站回家3091
- 7... 末9四段大厂实习|秋招收尾结束2981
- 8... 找到靠谱的公司,少走些弯路2760
- 9... 双非秋招timeline供参考(腾讯字节阿里快手美团)2511
- 10... 27届速通第一段前端实习后续--节孝子启动!2365
正在热议
更多
# 找工作中的小确幸 #
8603次浏览 93人参与
# 秋招踩过的“雷”,希望你别再踩 #
16992次浏览 193人参与
# 深信服秋招来了 #
280615次浏览 2917人参与
# 面包vs爱情,怎么选? #
16300次浏览 181人参与
# 实习在多还是在精 #
2250次浏览 41人参与
# 发面经攒人品 #
2338009次浏览 32559人参与
# 爱玛科技集团求职进展汇总 #
29828次浏览 208人参与
# 反问环节如何提问 #
106756次浏览 2003人参与
# 实习下班不想学习,正常吗? #
3075次浏览 48人参与
# 机械求职避坑tips #
67162次浏览 449人参与
# 校招谈薪一定要知道的事 #
2534次浏览 47人参与
# 你觉得什么岗位会被AI替代 #
4279次浏览 78人参与
# 贝壳求职进展汇总 #
36009次浏览 200人参与
# 机械人值得去的小众企业 #
24210次浏览 54人参与
# 浪潮求职进展汇总 #
17769次浏览 137人参与
# 秋招结束之后的日子 #
88369次浏览 985人参与
# 实习最想跑路的瞬间 #
81810次浏览 521人参与
# 你做过哪些dirty work #
19806次浏览 143人参与
# 选完offer后,你后悔学机械吗? #
39256次浏览 242人参与
# 投格力的你,拿到offer了吗? #
119036次浏览 686人参与
# 诺瓦星云求职进展汇总 #
219765次浏览 1715人参与
# 机械人,签完三方你在忙什么? #
61543次浏览 234人参与