为什么需要扩容?

因为HashMap为了节省创建出的对象的内存占用,一开始只默认分配:

static final int DEFAULT_INITIAL_CAPACITY=1<<4; 也就是默认的数组大小是16个,而在HashMap的源码中可以发现HashMap扩容方法如下,就是说当HashMap里存储元素的个数大于threshold(capacity*loadFactor时,会进行扩容,一般都会扩大成为原大小的一倍(总之是%2=0的一个newCapacity),之所以需要和2的幂相关,是因为散列表的hash算法是根据移位来进行计算的,而我们都知道计算机是二进制的,移位也只能是进行*2或者/2因此,扩容的大小要符合这个标准,否则会造成没必要的浪费甚至错误。

判断何时需要扩容

知道什么场景下会造成扩容,下面聊聊扩容是如何实现的:

扩容方法

首先判断原本的capacity是否已经是static final intMAXIMUM_CAPACITY=1<<30;,如果不是,会重新创建新的Entry数组,并将数组长度更改为newCapacity,接着调用了transfer方法,并将新的table和threshold赋值给当前hashMap对象,这里最重要的方法就是transfer,因为这个方法会根据newCapacity重新计算在Entry数组中原先存在的entry的新的散列位置。方法如下:

rehash重新计算entry的散列位置

计算过程比较简单与重新创建新的hashMap比较类似,就是根据entry的key重新计算出hash值,然后根据新的数组长度计算出应该把老的entry放在新数组的那个位置,如果有冲突就将entry链接其上。(这个方法一个有趣的地方是:是否rehash是可选的,而选择的方法是通过hash因子来决定的,这边暂时不多做讨论)在执行完这些东西之后,hashMap的扩容就结束了。

可以发觉,扩容的成本并不低,因为需要遍历一个时间复杂度为O(n)的数组,并且为其中的每个enrty进行hash计算。加入到新数组中,所以最好的情况是能够合理的使用HashMap的构造方法创建合适大小的HashMap,使得在不浪费内存的情况下,尽量减少扩容,这个就要根据业务来决定了。

另外引申一个问题,为什么hashMap会使用着么复杂的结构,而且在元素并没有将数组填充满的情况下就进行扩容?这个其实是和HashMap散列表的目的有关,因为使用hashCode先进行查找到entry所在的HashMap数组位置,再去遍历这个数组位置上的bucket,会使得查询的时间复杂度为O(1),这样一对比一般意义上的数组,不难发现有质的飞跃。这也是HashMap大费周章搞出这些的原因。而由此引申出来的冲突处理这样的问题后面会谈到。

hashmap 扩容是元素还是数组_谈谈HashMap扩容相关推荐

  1. 扩容是元素还是数组_数组是如何随机访问元素?数组下标为什么从0开始,而不是1?...

    作者:鹏磊 来源:搜云库技术团队 数组如何实现随机访问元素 什么是数组? 数组(Array)是一种线性表数据结构,它用一组连续的内存空间,来存储相同类型的数据. 什么是线性表(Linear List) ...

  2. hashmap 扩容是元素还是数组_曹工说JDK源码(1)--ConcurrentHashMap,扩容前大家同在一个哈希桶,为啥扩容后,你去新数组的高位,我只能去低位?...

    如何计算,一对key/value应该放在哪个哈希桶 大家都知道,hashmap底层是数组+链表(不讨论红黑树的情况),其中,这个数组,我们一般叫做哈希桶,大家如果去看jdk的源码,会发现里面有一些变量 ...

  3. hashmap 扩容是元素还是数组_HashMap的扩容机制---resize()

    面试的时候闻到了Hashmap的扩容机制,之前只看到了Hasmap的实现机制,补一下基础知识,讲的非常好 原文链接: Hashmap是一种非常常用的.应用广泛的数据类型,最近研究到相关的内容,就正好复 ...

  4. hashmap 扩容是元素还是数组_HashMap 中的容量与扩容实现

    总有人心里有火炬,而且彼此能看见. 高手过招,招招致命 JDK1.8 中 HashMap 的底层实现,我相信大家都能说上来个 一二,底层数据结构 数组 + 链表(或红黑树) ,源码如下/** * 数组 ...

  5. 扩容是元素还是数组_Map扩容源码

    首先我们运行一段代码: 此时运行,程序正常,接下来我们将注释放开: 此时运行发现,OOM了: 为什么new出来HashMap的时候并没有报OOM,而是在第一次进行put操作的时候才报的OOM?我们来看 ...

  6. 扩容是元素还是数组_02 数组(附ArrayList源码分析)

    定义 用一组连续的内存空间存储一组具有相同类型的数据的线性表数据结构. 优势 支持通过下标快速的随机访问数据,时间复杂度为O(1). 劣势 通常情况下,插入和删除效率低下,每次操作后,需要进行后续元素 ...

  7. 扩容是元素还是数组_Java中对数组的操作

    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对于数组的实现及处理也不尽相同. Java语言中提供的数组是用来存储固定大小的同类型元素.如:声明一个数组变量,numbers[100]来 ...

  8. java set中元素是数组_将HashSet中的元素转换为Java中的数组

    首先,创建一个HashSet及其元素-HashSet hs = new HashSet(); //将元素添加到哈希集 hs.add("B"); hs.add("A&quo ...

  9. arraylist扩容是创建新数组吗 java_Java ArrayList扩容问题实例详解

    本文研究的主要是Java ArrayList扩容问题实例详解的相关内容,具体介绍如下. 首先我们需要知道ArrayList里面的实质的其实是一个Object类型的数组,ArrayList的扩容问题其实 ...

最新文章

  1. Android--WebView显示Html,让其中的图片适应屏幕宽度
  2. 如何从WebSocket服务器收到的数据判断出有哪些客户端需要广播
  3. OneOfT1,…,Tn清新
  4. 如何在 ASP.NET Core 中使用 API 分析器
  5. python附加索引_python – 附加两个多索引的pandas数据帧
  6. git rebase 调整commit顺序
  7. springboot+shiro+jwt实现token认证登录
  8. 如何在xshell中查看某一接口的服务_【干货分享】如何使用远程工具进入Linux系统...
  9. 基于数值数据理解和重要信息验证的数据到文本生成模型
  10. Luogu P2833 等式 我是傻子x2
  11. VM虚拟机下载及安装教程
  12. 如何全面系统的自学Java?(附2022最新整理Java学习路线)
  13. 饥荒联机一直显示正在启动服务器,饥荒联机版启动服务器时间长 | 手游网游页游攻略大全...
  14. 微信公众号开发之消息模板
  15. 黑马程序员:一些简单的设计模式
  16. 超详细总结:python的转义字符及用法
  17. daniel powter
  18. [转]天文方法计算二十四节气
  19. BIG6——解决问题时收集、利用资料的思路
  20. nature:逆转关闭的免疫细胞保护大脑老化

热门文章

  1. 修改IDEA中Java代码的默认注释风格
  2. Android电量图标实现
  3. 获得预测值之后的步骤(导入arcgis)
  4. Flutter | 分享一个简单好用的输入验证码控件
  5. vlang 之 vpm 使用
  6. 树状数组-Java代码纯享版
  7. 狂野飙车9显示无法连接服务器,狂野飙车9:竞速传奇无法连接服务器如何解决...
  8. 共享单车计算机网络,基于BP神经网络的共享单车调度优化
  9. 红米手机1内部存储空间不足怎么办?
  10. CVPR 2022 | 图森未来提出小目标检测工作QueryDet:使用级联稀疏query加速高分辨率下的小目标检测...