Java源码分析(三)ArrayList
ArrayList是我们经常用到的一个集合类。数组在创建时就要给一个明确的大小,而ArrayList的长度是可以动态调整的,因此,也叫动态数组。那么本篇我们一起学习下ArrayList的源码。
一、创建ArrayList
首先,我们从创建ArrayList开始。上面也提到过,ArrayList的长度是可以动态调整的,我们通常创建一个不指定容量的数组。例如如下代码,创建一个空的ArrayList:
List<String> list = new ArrayList<>();
看下构造方法的源码:


代码注释说:构建一个容量为10的空List。List是基于数组来实现的,可以看到,构造方法这里创建了一个空的数组。咦?没看到容量为10啊,这个后面我们会介绍到。
二、添加元素
1、add
创建好一个空的ArrayList后,我们调用add方法往里面添加元素,如下:
list.add("a");
list.add("b");
list.add("c");
看下add方法的源码:

核心是调用了红框中的add方法,看下其实现:

可以看到,判断size是否达到了数组的长度,如果达到了长度,调用grow()方法扩容,然后把元素赋值给size的位置,对size加1。 简单总结:
1扩容2赋值3加一。
2、扩容原理
接下来,看下grow函数是怎么扩容的:

基于当前的数组和新的容量(size + 1)复制新的容量的数组 ,看下newCapacity函数是如何去确定新的数组的容量的:

代码注释机翻一下:返回至少与给定最小容量一样大的容量。如果足够的话,返回增加50%的当前容量。除非给定的最小容量大于MAX_ARRAY_SIZE,否则不会返回大于MAX_ARRAY_SIZE的容量。 在扩容的操作里面,用到了几个常量:
private static final int DEFAULT_CAPACITY = 10;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
@Native public static final int MAX_VALUE = 0x7fffffff;
所以,扩容是这样的过程:
1、new = old + old *(old / 2): 扩容50%得到newCapacity
2、如果newCapacity - 最小容量(即size + 1)<=0,返回给定最小容量。需要注意,如果空的数组,那么返回的容量是10。
这里再详细解释下:
往一个空的list去add元素,size = 0,minCapacity = size + 1,计算出的newCapacity = 0 + 0 = 0,这时候newCapacity - minCapacity = -1,满足了条件。然后这时候判断数组是空的,所以返回了max(10,1),也就是10。
那么接下来继续add元素,容量为10,因此在添加到10个元素之前,都不会扩容。直到添加第11个元素的时候,触发扩容,这时候就是扩容50%了。
return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity: hugeCapacity(minCapacity);
绝大多数情况下返回newCapacity,也就是扩容50%的容量,当新的容量超过MAX_ARRAY_SIZE,会走到hugeCapacity的逻辑:

总结下,ArrayList添加元素时的扩容流程:
1、新建的ArrayList容量10其实不准确,为0。
2、当首次添加元素时,容量扩展为默认容量10。
3、一直到添加满10个元素之前,都不会再次扩容,维持10的容量。
4、添加第11个元素时,会触发扩容50%;直到用完容量前,不会继续扩容,以此类推。
3、扩容demo验证
接下来,我们写一个小的demo验证下扩容的流程:
public class ArrayListTest {public static void main(String[] args) {// 创建一个空的ArrayListArrayList<Integer> list = new ArrayList<>();System.out.println("初始容量:" + getArrayListCapacity(list));for (int i = 0; i < 11; i++) {list.add(i);System.out.println("add第" + (i + 1) + "个元素,容量:" + getArrayListCapacity(list));}}/*** 反射获取Arraylist的容量* @param list* @return*/private static int getArrayListCapacity(ArrayList<?> list) {try {java.lang.reflect.Field capacityField = ArrayList.class.getDeclaredField("elementData");capacityField.setAccessible(true);return ((Object[]) capacityField.get(list)).length;} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();return -1;}}

三、移除元素
移除元素使用remove方法,如下:

(1)检验index,index非法则会抛出异常:IndexOutOfBoundsException
(2)把index的元素赋值给oldValue,并在程序最后返回该element
(3)调用fastRemove方法移除第index个元素
看下fastRemove方法:
基于当前的数组去把指定范围的数据copy到另一个数组,并把
相关文章:
Java源码分析(三)ArrayList
ArrayList是我们经常用到的一个集合类。数组在创建时就要给一个明确的大小,而ArrayList的长度是可以动态调整的,因此,也叫动态数组。那么本篇我们一起学习下ArrayList的源码。 一、创建ArrayList 首先,我们从创建ArrayList开始。…...
冒泡排序
贵阳这个地方的天气变化好大呀,前两天晒大太阳,今天就冷的脚抖,简直不要太冷,但是不管怎么样,还是要学习的哟! 冬天来了,春天确实还有一点远! 好了,话不多说,…...
docker基于debian11基础环境安装libreoffice
首先下载指定版本的libreoffice,注意debian11下需要选择Linux (64-bit) (deb) 官方下载地址:https://www.libreoffice.org/download/download-libreoffice/?typedeb-x86_64&version7.6.2&langzh-CN 将文件上传到服务器并解压缩备用,…...
【正点原子STM32连载】 第五十章 FATFS实验 摘自【正点原子】APM32F407最小系统板使用指南
1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html## 第五…...
12. 机器学习——评价指标
机器学习面试题汇总与解析——评价指标 本章讲解知识点 什么是评价指标?机器学习本专栏适合于Python已经入门的学生或人士,有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是…...
代码随想录算法训练营第23期day45|70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数
目录 一、(leetcode 70)爬楼梯 二、(leetcode 322)零钱兑换 三、(leetcode 279)完全平方数 一、(leetcode 70)爬楼梯 力扣题目链接 状态:查看思路后AC 除…...
uniapp公共css
/* 弹性布局 */ .flex{display: flex; } .a-c{align-items: center; } .a-s{align-items: flex-start; } .a-e{align-items: flex-end; } .j-c{justify-content: center; } .j-sb{justify-content: space-between; } .j-s{justify-content: flex-start; } .j-e{justify-content…...
C语言—i++、++i、条件运算符、goto语句、注释
i和i #include <stdio.h> int main() {int i5,j;j i;printf("i%d,j%d\n", i, j);i 5;j i;printf("i%d,j%d\n", i, j);system("pause");return 0;}i6,j6 i6,j5 请按任意键继续. . .条件运算符 goto语句 #include <stdio.h> int …...
Java自学第8课:电商项目(3) - 重新搭建环境
由于之前用的jdk和eclipse,以及mysql并不是视频教程所采用的,在后面运行源码和使用作者提供源码时,总是报错,怀疑: 1 数据库有问题 2 jdk和引入的jar包不匹配 3 其他什么未知的错误? 所以决定卸载jdk e…...
深度学习_11_softmax_图片识别代码原理解析
完整代码: import torch from d2l import torch as d2l"创建训练集&创建检测集合" batch_size 256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size)"每个图片长度,以及图片种类" num_inputs 784 num_output…...
Java Web——前端HTML入门
目录 HTML&CSS3&JavaScript简述 1. HTML概念 2. 超文本 3. 标记语言 4. HTML基础结构 5. HTML基础词汇 6. HTML语法规则 7. VS Code 推荐使用的插件 8. 在线帮助文档 HTML&CSS3&JavaScript简述 HTML 主要用于网页主体结构的搭建,像一个毛坯…...
华为ensp:为vlan配置ip
配置对应vlan的ip vlan1 interface Vlanif 1 进入vlan1 ip address 192.168.1.254 24配置IP为192.168.1.254 子网掩码为24位 这样就配置上ip了 vlan2 interface Vlanif 2 ip address 192.168.2.254 24 vlan3 interface Vlanif 3 ip address 192.168.3.254 24 查看结果 …...
laravel8-rabbitmq消息队列-实时监听跨服务器消息
使用场景介绍: 1)用于实时监听远程服务器发出的消息(json格式消息),接受并更新消息状态,存储到本地服务器 2)环境:lNMP(laravel8) 3)服务器需要开…...
git清除历史提交记录保持本地文件不变
https://www.cnblogs.com/langkyeSir/p/14528857.html git删除历史版本,保留当前状态。 有时候,我们误提交了某些隐私文件,使用git rm xxx删除后,其实版本库中是有历史记录的,想要删除这些记录,但是又不想…...
SOME/IP学习笔记2
1. SOME/IP 协议 SOME/IP目前支持UDP(用户传输协议)和TCP(传输控制协议), PS:UDP和TCP区别如下 TCP面向连接的,可靠的数据传输服务;UDP面向无连接的,尽最大努力的数据传输服务&…...
python实现FINS协议的TCP服务端(篇一)
python实现FINS协议的TCP服务端是一件稍微麻烦点的事情。它不像modbusTCP那样,可以使用现成的pymodbus模块去实现。但是,我们可以根据协议帧进行组包,自己去实现帧的格式,而这一切可以基于socket模块。本文为第一篇。 一、了解FI…...
利用uni-app 开发的iOS app 发布到App Store全流程
1.0.3 20200927 更新官方对应用审核流程的状态。 注:最新审核后续将同步社区另一篇记录 AppStore 审核被拒原因记录及解决措施 :苹果开发上架常见问题 | appuploader使用教程 1.0.2 20200925 新增首次驳回拒绝邮件解决措施。 1.0.1 20200922 首次…...
5个高质量的实用办公软件,每一款都是良心推荐
在现代办公环境中,高效的办公软件可以极大地提升工作效率,简化工作流程,帮助我们更好地完成工作。今天就给大家分享5个高质量的实用办公软件,每一款都是良心推荐。 01、FastStone Capture(截图工具) FastSt…...
基于GPTs个性化定制SCI论文专业翻译器
1. 什么是GPTs GPTs是OpenAI在2023年11月6日开发者大会上发布的重要功能更新,允许用户根据特定需求定制自己的ChatGPT模型。 Introducing GPTs 官方介绍页面https://openai.com/blog/introducing-gpts 在原有自定义ChatGPT的流程中,首先需要自己编制p…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
