面试笔记--HashMap扩容机制
转载请注明出处 http://www.cnblogs.com/yanzige/p/8392142.html
扩容必须满足两个条件:
1、 存放新值的时候当前已有元素的个数必须大于等于阈值
2、 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
如果需要扩容,调用扩容的方法resize()
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
//判断是否有超出扩容的最大值,如果达到最大值则不进行扩容操作
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
// transfer()方法把原数组中的值放到新数组中
transfer(newTable, initHashSeedAsNeeded(newCapacity));
//设置hashmap扩容后为新的数组引用
table = newTable;
//设置hashmap扩容新的阈值
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
transfer()在实际扩容时候把原来数组中的元素放入新的数组中
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
//通过key值的hash值和新数组的大小算出在当前数组中的存放位置
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
Hashmap的扩容需要满足两个条件:当前数据存储的数量(即size())大小必须大于等于阈值;当前加入的数据是否发生了hash冲突。
因为上面这两个条件,所以存在下面这些情况
(1)、就是hashmap在存值的时候(默认大小为16,负载因子0.75,阈值12),可能达到最后存满16个值的时候,再存入第17个值才会发生扩容现象,因为前16个值,每个值在底层数组中分别占据一个位置,并没有发生hash碰撞。
(2)、当然也有可能存储更多值(超多16个值,最多可以存26个值)都还没有扩容。原理:前11个值全部hash碰撞,存到数组的同一个位置(这时元素个数小于阈值12,不会扩容),后面所有存入的15个值全部分散到数组剩下的15个位置(这时元素个数大于等于阈值,但是每次存入的元素并没有发生hash碰撞,所以不会扩容),前面11+15=26,所以在存入第27个值的时候才同时满足上面两个条件,这时候才会发生扩容现象。
面试笔记--HashMap扩容机制的更多相关文章
- HashSet保证元素唯一原理以及HashMap扩容机制
一.HashSet保证元素唯一原理: 依赖于hashCode()和equals()方法1.唯一原理: 1.1 当HashSet集合要存储元素的时候,会调用该元素的hashCode()方法计算哈希值 1 ...
- HashMap扩容机制
1.什么是resize: resize就是重新计算容量:当我们不断的向HashMap对象里不停的添加元素时,HashMap对象内部的数组就会出现无法装载更多的元素,这是对象就需要扩大数组的长度,以便能 ...
- HashMap 扩容机制
引用于: http://www.cnblogs.com/hongdada/p/6024832.html HashMap: public HashMap(int initialCapacity, flo ...
- Java中HashMap扩容机制思考
1. HashMap在什么条件下扩容 判断HashMap的数组Size大小如果超过loadFactor*capacity,就要扩容. 相关的类属性: capacity:当前数组容量,始终保持 2^n, ...
- java源码--HashMap扩容机制学习
待完成 Java中hash算法细述 https://blog.csdn.net/majinggogogo/article/details/80260400 java HashMap源码分析(JDK8) ...
- 深入理解HashMap的扩容机制
什么时候扩容: 网上总结的会有很多,但大多都总结的不够完整或者不够准确.大多数可能值说了满足我下面条件一的情况. 扩容必须满足两个条件: 1. 存放新值的时候当前已有元素的个数必须大于等于阈值 2. ...
- HashMap自动扩容机制源码详解
一.简介 HashMap的源码我们之前解读过,数组加链表,链表过长时裂变为红黑树.自动扩容机制没细说,今天详细看一下 往期回顾: Java1.7的HashMap源码分析-面试必备技能 Java1.8的 ...
- java集合专题 (ArrayList、HashSet等集合底层结构及扩容机制、HashMap源码)
一.数组与集合比较 数组: 1)长度开始时必须指定,而且一旦指定,不能更改 2)保存的必须为同一类型的元素 3)使用数组进行增加/删除元素-比较麻烦 集合: 1)可以动态保存任意多个对象,使用比较方便 ...
- HashMap底层结构、原理、扩容机制
https://www.jianshu.com/p/c1b616ff1130 http://youzhixueyuan.com/the-underlying-structure-and-princip ...
随机推荐
- 小程序实践(二):swiper组件实现轮播图效果
swiper组件类似于Android中的ViewPager,实现类似轮播图的效果,相对于Android的Viewpager,swiper实现起来更加方便,快捷. 效果图: 首先看下swiper支持的属 ...
- 转载:如何在Ubuntu 18.04上使用UFW设置防火墙
https://blog.csdn.net/u013068789/article/details/82051943 介绍 UFW或Uncomplicated Firewall是iptables一个接口 ...
- (网页)HTML5
1.html5基本格式: <!DOCTYPE> --> 文档类型声明. <html lang="zh-cn"> --> 表示html文档开始 & ...
- Bullet3的一些理解
Bullet3应该是第三大物理引擎了,拥有宽松的授权方式,开源.在我的项目中将采用它. 碰撞世界(btCollisionWorld)是最基本的环境类. 动态世界(btDynamicsWorld)从碰撞 ...
- Git基本操作和GtHub 特殊技巧
<GitHub 入门与实践> 笔记 了解GitHub Git 和 GitHub 的区别 在Git中,开发者将源代码存入名为"Git仓库"的资料库中,并加以使用.而Git ...
- 堆栈的应用——用JavaScript描述数据结构
栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把另一端称为栈底. 一.实现一个栈类Stack 基于堆栈的特性,可以用数组做线 ...
- 软件工程:java实现wc项目基本功能
项目相关要求 项目地址:https://github.com/xiawork/wcwork 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功能,并能够快速地处理多个 ...
- Hive内部表与外部表的区别
1.未被external修饰的是内部表[managed table],被external修饰的为外部表[external table]. 2.内部表数据由Hive自身管理,外部表数据由HDFS管理. ...
- IDEA实用插件Lombok
Lombok Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法.通常,我们所定义的对象和be ...
- ORACLE实际执行计划与预估执行计划不一致性能优化案例
在一台ORACLE服务器上做巡检时,使用下面SQL找出DISK_READ最高的TOP SQL分析时,分析过程中,有一条SQL语句的一些反常现象,让人觉得很奇怪: SELECT SQL_ID, ...