通过源码⼀步⼀步分析 ArrayList 扩容机制
ArrayList
是 Java 中常用的集合类,它底层实现是基于数组的。为了处理元素的动态增加,ArrayList
会在容量不足时进行扩容。以下是通过源码逐步分析 ArrayList
扩容机制的过程。
1. ArrayList
类的基本结构
ArrayList
继承自 AbstractList
,实现了 List
接口。其底层数据结构是一个数组,初始时,ArrayList
会为其元素分配一个初始容量。ArrayList
还包含一个成员变量 elementData
,它是一个数组,用来存储集合中的元素。
public class ArrayList<E> extends AbstractList<E> implements List<E> {private Object[] elementData;private int size;private static final int DEFAULT_CAPACITY = 10; // 默认容量private static final Object[] EMPTY_ELEMENTDATA = {}; // 空数组public ArrayList() {this.elementData = EMPTY_ELEMENTDATA; // 初始为空数组}public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity]; // 根据传入的初始容量创建数组} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA; // 如果容量为0,使用空数组} else {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}}// 省略其他构造函数和方法
}
2. 添加元素时的扩容逻辑
ArrayList
中的元素是通过 add(E e)
方法添加的。当元素的数量超过当前数组的容量时,ArrayList
会触发扩容。我们可以从 add
方法的源码分析其扩容的实现。
public boolean add(E e) {ensureCapacityInternal(size + 1); // 确保容量足够elementData[size++] = e; // 将元素添加到数组中,并更新sizereturn true;
}
3. ensureCapacityInternal
方法
ensureCapacityInternal
方法是扩容的关键。它首先检查当前数组容量是否足够,如果不足,就会进行扩容。源码如下:
private void ensureCapacityInternal(int minCapacity) {// 如果elementData为空(即初次初始化),则使用默认容量if (elementData == EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}// 如果当前容量不足以容纳更多元素,则进行扩容if (minCapacity - elementData.length > 0)grow(minCapacity);
}private void grow(int minCapacity) {// 获取当前数组的容量int oldCapacity = elementData.length;// 扩容时的默认增长策略为当前容量的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1); // oldCapacity + oldCapacity / 2// 如果扩容后容量不足,使用最小的扩容容量if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 如果新容量为0,意味着容量已超出限制,抛出异常if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 扩容:创建一个新的数组并将旧数组元素复制过去elementData = Arrays.copyOf(elementData, newCapacity);
}private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private static int hugeCapacity(int minCapacity) {// 如果容量超出最大值,抛出异常if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
4. 扩容的逻辑解析
- 初始容量处理:当
ArrayList
创建时,初始容量为 0 或者通过构造函数指定的容量。如果容量为 0,则elementData
为空数组。 - 容量不够时扩容:
- 当
elementData
容量不够时,ensureCapacityInternal
会调用grow
方法进行扩容。 - 扩容时,新数组的容量是旧数组容量的 1.5 倍。
- 如果扩容后的容量仍然不足以容纳新元素,容量会直接增长到满足最小需求的大小。
- 如果容量增长到达
Integer.MAX_VALUE
限制,会使用hugeCapacity
方法,确保不会超过 Java 数组的最大长度。
- 当
5. 扩容过程的影响
- 性能影响:每次扩容时,
ArrayList
需要创建一个新的数组并将旧数组的元素复制过去。这是一个 O(n) 的操作,其中 n 是当前数组的大小。 - 内存利用率:通过 1.5 倍扩容,
ArrayList
保证了增长的合理性,避免了频繁的扩容带来的性能开销,但也可能导致一定程度的内存浪费,尤其是在扩容多次时。
总结
ArrayList
的扩容机制主要由以下几个步骤组成:
- 容量检查:每次添加元素时,先检查当前数组是否有足够的容量。
- 扩容计算:如果容量不足,则按照 1.5 倍的增长策略进行扩容。
- 数组复制:扩容时,通过
Arrays.copyOf
将旧数组的数据复制到新数组中。 - 容量上限:当容量超出最大限制时,抛出
OutOfMemoryError
。
这个机制可以确保 ArrayList
在动态扩展时既高效又不会造成过多的内存浪费。
相关文章:
通过源码⼀步⼀步分析 ArrayList 扩容机制
ArrayList 是 Java 中常用的集合类,它底层实现是基于数组的。为了处理元素的动态增加,ArrayList 会在容量不足时进行扩容。以下是通过源码逐步分析 ArrayList 扩容机制的过程。 1. ArrayList 类的基本结构 ArrayList 继承自 AbstractList,实…...
源码分析之Openlayers中默认Controls控件渲染原理
概述 Openlayers 中默认的三类控件是Zoom、Rotate和Attribution 源码分析 defaults方法 Openlayers 默认控件的集成封装在defaults方法中,该方法会返回一个Collection的实例,Collection是一个基于数组封装了一些方法,主要涉及到数组项的添…...
中间件的分类与实践:从消息到缓存
目录 一. 中间件的基本概念 二. 中间件的主要类型 (1)消息中间件(Message-Oriented Middleware, MOM): (2)数据库中间件: (3)Web中间件: &a…...
京东e卡 h5st 4.96
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 有相关问题请第一时间头像私信联系我删…...
《CSS 知识点》滚动条仅在 hover 时才显示(宽度不改变)
很简单! 滚动条的滑动小方块背景色默认透明,仅在hover时设置背景色; 滚动条的轨道背景色默认透明,仅在hover时设置背景色; /*滚动条的滑动小方块*/ ::-webkit-scrollbar-thumb {background: transparent; } /*hover…...
手里有病理切片+单细胞测序的数据,如何开展医工交叉的研究?
小罗碎碎念 这一期推文研究一个问题:病理如何与单细胞结合? 病理与单细胞的结合,时常出现在今年的各大顶刊中。 关于这一领域的研究,其实19年就开始了。我把部分低质量的文献做了剔除,但是也基本能反应这一领域的受关注…...
力矩扭矩传感器介绍
在机械臂(机器人臂)末端使用的力矩扭矩传感器主要用于测量机械臂末端执行器(例如机械手爪、抓取装置等)所受的扭矩和力。这些传感器对机械臂的控制系统至关重要,能够提供精确的力反馈信息,帮助实现更高效、…...
【Appium】AttributeError: ‘NoneType‘ object has no attribute ‘to_capabilities‘
目录 1、报错内容 2、解决方案 (1)检查 (2)报错原因 (3)解决步骤 3、解决结果 1、报错内容 在PyCharm编写好脚本后,模拟器和appium也是连接成功的,但是运行脚本时报错&…...
QT 中 多线程(备查)
基础 一个线程处理窗口事件,其他线程进行逻辑运算 在QT中使用多线程,需要额外注意的: 1)默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新 2)子线程负责后台…...
第八十六条:在实现serializable接口时要特别谨慎
要想使一个类的实例可被序列化,非常简单,只要在它的声明中加入"implements Serializable"字样即可。虽然使一个类可被序列化的直接开销低到甚至可以忽略不计,但是为了序列化而付出的长期开销往往是实实在在的。 为实现Serializable…...
【Elasticsearch 中间件】Elasticsearch 客户端使用案例
文章目录 一、安装 Elasticsearch1.1 启动 Elasticsearch1.2 启动 Kibana 二、客户端代码2.1 导入依赖2.2 配置 application.yaml2.3 定义实体类2.4 连接 Elasticserach2.5 定义 Service 层接口2.6 实现 Service 层功能 三、测试项目3.1 添加数据3.2 搜索数据3.3 更新数据3.4 删…...
深入理解MySQL中的ONLY_FULL_GROUP_BY
在MySQL数据库管理中,ONLY_FULL_GROUP_BY是一个重要的SQL模式,它直接影响着GROUP BY语句的执行方式和结果。本文将从基础概念出发,逐步解析ONLY_FULL_GROUP_BY的工作原理、应用场景及应对策略。 什么是ONLY_FULL_GROUP_BY? ONLY…...
获得日志记录之外的新视角:应用程序性能监控简介(APM)
作者:来自 Elastic David Hope 日志记录领域即将发生改变。在这篇文章中,我们将概述从单纯的日志记录到包含日志、跟踪和 APM 的完全集成解决方案的推荐流程。 通过 APM 和跟踪优先考虑客户体验 企业软件开发和运营已成为一个有趣的领域。我们拥有一些非…...
如何避免缓存击穿?超融合常驻缓存和多存储池方案对比
作者:SmartX 解决方案专家 钟锦锌 很多运维人员都知道,混合存储介质配置可能会带来“缓存击穿”的问题,尤其是大数据分析、数据仓库等需要频繁访问“冷数据”的应用场景,缓存击穿可能会更频繁地出现,影响业务运行。除…...
口语笔记——祈使句用法
省略主语 (You give me) a cup of tea, please. 一杯茶(You wait for) another minute. 两等一分钟(You) keep quiet. 保持安静give me a break. 饶了我吧take your hand off. 把你的手拿开take this thing away 把这东西拿开never talk to strangers. 永远不要跟陌生人说话Do…...
SQL连续登录问题(详细案例分析)
如果要统计用户活跃度,那就涉及连续登录问题,接下来将举一个简单的例子来详细说明这个问题: 一、创建一些模拟数据 一些测试数据如下: deviceid1,2022-10-26,2022-10-26,2022-11-01 deviceid1,2022-10-26,2022-11-03,2022-11-0…...
Next.js 系统性教学:深入理解缓存与数据优化策略
更多有关Next.js教程,请查阅: 【目录】Next.js 独立开发系列教程-CSDN博客 目录 前言 1. 缓存的基本概念 1.1 缓存的作用 1.2 Next.js 中的缓存策略 2. Next.js 的缓存机制 2.1 请求记忆化(Request Memoization) 2.1.1 什…...
【PyTorch】(基础六)---- 搭建卷积神经网络
关于神经网络中激活函数、卷积层、池化层等底层原理,我不会在本文中详解,但是关于pytorch中如何使用对应的方法实现这些层的功能我会进行解释,如果你想要了解一些关于神经网络底层的知识,我十分推荐你去看一下吴恩达老师的深度学习…...
【JAVA项目】基于ssm的【美食推荐管理系统】
【JAVA项目】基于ssm的【美食推荐管理系统】 技术简介:采用JSP技术、B/S架构、SSM框架、MySQL技术等实现。 系统简介:美食推荐管理系统,在系统首页可以查看首页、热门美食、美食教程、美食店铺、美食社区、美食资讯、我的、跳转到后台等内容。…...
adb 常用命令笔记
adb connect <ip> #连接指定ip adb disconnect <ip> #断开连接指定ip adb devices #查看连接中的设备 adb install <flie> #安装apk adb uninstall <packageName> #卸载app adb -s install <flie> #指定设备安装 adb shell pm list package…...
[代码随想录Day32打卡] 理论基础 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯
理论基础 题型 动归基础(这一节就是基础题)背包问题打家劫舍股票问题子序列问题 动态规划五部曲 确定dp数组及其下标的含义确定递推公式dp数组如何初始化遍历顺序打印dp数组 509. 斐波那契数 简单~ dp数组及下标含义: dp[i]表示第i各斐…...
android NumberPicker隐藏分割线或修改颜色
在 Android 中,可以通过以下几种方法隐藏 NumberPicker 的分割线: 使用 XML 属性设置 在布局文件中的 NumberPicker 标签内添加 android:selectionDividerHeight"0dp" 属性,将分割线的高度设置为 0,从而达到隐藏分割线…...
7-2 二分查找
输入n值(1<n<1000)、n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数。若x不存在,输出-1和比较次数。 输入格式: 输入共三行: 第一行是n值࿱…...
mid360使用cartorapher进行3d建图导航
1. 添加urdf配置文件: 添加IMU配置关节点和laser关节点 <!-- imu livox --> <joint name"livox_frame_joint" type"fixed"> <parent link"base_link" /> <child link"livox_frame" /> <o…...
Ubuntu安装grafana
需求背景:管理服务器,并在线预警,通知 需求目的: 及时获取服务器状态 技能要求: 1、ubuntu 2、grafana 3、prometheus 4、node 步骤: 一、grafana安装 1、准备系统环境,配置号网络 2、…...
Java版-图论-最短路-Floyd算法
实现描述 网络延迟时间示例 根据上面提示,可以计算出,最大有100个点,最大耗时为100*wi,即最大的耗时为10000,任何耗时计算出来超过这个值可以理解为不可达了;从而得出实现代码里面的: int maxTime 10005…...
可视化建模以及UML期末复习篇----UML图
这是一篇相对较长的文章,如你们所见,比较详细,全长两万字。我不建议你们一次性看完,直接跳目录找你需要的知识点即可。 --------欢迎各位来到我UML国! 一、UML图 总共有如下几种: 用例图(Use Ca…...
HTML常见标签列表,涵盖了多种用途的标签。
文档结构标签 <!DOCTYPE html>:声明文档类型,告诉浏览器使用HTML5标准。<html>:HTML文档的根元素。<head>:包含文档的元数据(meta-data),如标题、字符集、样式表链接、脚本等…...
FPGA 16 ,Verilog中的位宽:深入理解与应用
目录 前言 一. 位宽的基本概念 二. 位宽的定义方法 1. 使用向量变量定义位宽 ① 向量类型及位宽指定 ② 位宽范围及位索引含义 ③ 存储数据与字节数据 2. 使用常量参数定义位宽 3. 使用宏定义位宽 4. 使用[:][-:]操作符定义位宽 1. 详细解释 : 操作符 -: 操作符 …...
vue-生命周期
Vue 的生命周期是指 Vue 实例从创建到销毁期间经历的一系列阶段。每个阶段都有相应的钩子函数(Lifecycle Hooks),允许开发者在这些关键时刻执行自定义逻辑。 一、钩子函数 1. 创建阶段 beforeCreate 在实例初始化之后,数据观测 …...
网站开发的书/关键词排名查询网站
转自:http://www.jb51.net/article/84924.htm取整(向下取整):复制代码代码如下:select floor(5.534) from dual;select trunc(5.534) from dual;上面两种用法都可以对数字5.534向下取整,结果为5.如果要向上取整 ,得到结果为6&…...
wordpress iis 伪静态/百度竞价排名多少钱
作者:杨涛涛资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课…...
快速建设网站视频教程/网络营销的营销理念
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以…...
网站建设的市场定位分析/什么是精准营销
SpringBoot集成的Activiti6.0代码(绘制工具界面代码 审批代码) 最近主管需要我搭建一个基于Activiti6.0引擎的工作流平台,在配置好Tomcat并成功运行Activiti6.0官网所提供的war包后,在平台上创建了一个二级审批流程,…...
搭建网站教程视频/关键词优化公司哪家好
我有一些没有主键的列,并且要添加一个主键列.NAME Age-------------Peter 45Bob 25John 56Peter 45这很好,但我的客户使用数据库用户没有权限添加序列或触发器.我想阻止联系数十名DBA管理员来更改用户权限或运行我的脚本.这是我的建议,只添加一个更新语句的PK:(我需…...
无锡高端网站建设公司哪家好/楚雄今日头条新闻
题意 题目链接 Sol 比较套路吧,设\(f[i][j]\)表示以\(i\)为根的子树中选了\(j\)个黑点对答案的贡献 然后考虑每条边的贡献,边的两边的答案都是可以算出来的 转移的时候背包一下。 #include<bits/stdc.h> #define Pair pair<int, int> #defin…...