热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

面试题:说说HashMap的扩容过程?

这是一道阿里的面试题,考察你对HashMap源码的了解情况,废话不多说,咱们就直接上源码吧!jdk1.7源码voidre

  这是一道阿里的面试题,考察你对HashMap源码的了解情况,废话不多说,咱们就直接上源码吧!


jdk 1.7 源码

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];//创建一个新数组boolean oldAltHashing = useAltHashing;useAltHashing |= sun.misc.VM.isBooted() &&(newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);boolean rehash = oldAltHashing ^ useAltHashing;//是否需要重新计算hash值transfer(newTable, rehash);//将oldTable的元素迁移到newTabletable = newTable;//将新数组重新赋值//重新计算阈值threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
void transfer(Entry[] newTable, boolean rehash) {int newCapacity &#61; newTable.length;for (Entry<K,V> e : table) {//遍历oldTable迁移元素到newTablewhile(null !&#61; e) {//①处会导致闭环&#xff0c;从而导致e永远不为空&#xff0c;然后死循环&#xff0c;内存直接爆了Entry<K,V> next &#61; e.next;if (rehash) {//是否需要重新计算hash值e.hash &#61; null &#61;&#61; e.key ? 0 : hash(e.key);}int i &#61; indexFor(e.hash, newCapacity);e.next &#61; newTable[i];//①newTable[i] &#61; e;//①e &#61; next;//①}}
}

jdk 1.8 源码(比较长&#xff0c;慢慢品哈)

final Node<K,V>[] resize() {Node<K,V>[] oldTab &#61; table;//保存旧数组int oldCap &#61; (oldTab &#61;&#61; null) ? 0 : oldTab.length;int oldThr &#61; threshold;//保存旧阈值int newCap, newThr &#61; 0;//创建新的数组大小、新的阈值if (oldCap > 0) {if (oldCap >&#61; MAXIMUM_CAPACITY) {//判断当前数组大小是否达到最大值threshold &#61; Integer.MAX_VALUE;return oldTab;}else if ((newCap &#61; oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >&#61; DEFAULT_INITIAL_CAPACITY)newThr &#61; oldThr << 1; //扩容两倍的阈值}else if (oldThr > 0) // 初始化新的数组大小newCap &#61; oldThr;else {//上面条件都不满足&#xff0c;则使用默认值newCap &#61; DEFAULT_INITIAL_CAPACITY;newThr &#61; (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr &#61;&#61; 0) {//初始化新的阈值float ft &#61; (float)newCap * loadFactor;newThr &#61; (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?(int)ft : Integer.MAX_VALUE);}threshold &#61; newThr;//将新阈值赋值到当前对象&#64;SuppressWarnings({"rawtypes","unchecked"})//创建一个newCap大小的数组NodeNode<K,V>[] newTab &#61; (Node<K,V>[])new Node[newCap];table &#61; newTab;if (oldTab !&#61; null) {for (int j &#61; 0; j < oldCap; &#43;&#43;j) {//遍历旧的数组Node<K,V> e;if ((e &#61; oldTab[j]) !&#61; null) {oldTab[j] &#61; null;//释放空间if (e.next &#61;&#61; null)//如果旧数组中e后面没有元素&#xff0c;则直接计算新数组的位置存放newTab[e.hash & (newCap - 1)] &#61; e;else if (e instanceof TreeNode)//如果是红黑树则单独处理((TreeNode<K,V>)e).split(this, newTab, j, oldCap);else { //链表结构逻辑&#xff0c;解决hash冲突Node<K,V> loHead &#61; null, loTail &#61; null;Node<K,V> hiHead &#61; null, hiTail &#61; null;Node<K,V> next;do {next &#61; e.next;if ((e.hash & oldCap) &#61;&#61; 0) {if (loTail &#61;&#61; null)loHead &#61; e;elseloTail.next &#61; e;loTail &#61; e;}else {if (hiTail &#61;&#61; null)hiHead &#61; e;elsehiTail.next &#61; e;hiTail &#61; e;}} while ((e &#61; next) !&#61; null);//原索引放入数组中if (loTail !&#61; null) {loTail.next &#61; null;newTab[j] &#61; loHead;}//原索引&#43;oldCap放入数组中if (hiTail !&#61; null) {hiTail.next &#61; null;newTab[j &#43; oldCap] &#61; hiHead;//jdk1.8优化的点}}}}}return newTab;}

总结

  jdk1.7扩容是重新计算hash&#xff1b;jdk1.8是要看看原来的hash值新增的那个bit是1还是0好了&#xff0c;如果是0则索引没变&#xff0c;如果是1则索引变成"原索引&#43;oldCap".这是jdk1.8的亮点&#xff0c;设计的确实非常的巧妙&#xff0c;即省去了重新计算hash值得时间&#xff0c;又均匀的把之前的冲突的节点分散到新的数组bucket上

  jdk1.7在rehash的时候&#xff0c;旧链表迁移到新链表的时候&#xff0c;如果在新表的数组索引位置相同&#xff0c;则链表元素会倒置&#xff0c;但是jdk1.8不会倒置


推荐阅读
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
author-avatar
透明
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有