java集合中ArrayList源码解析是怎样的
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,今天就跟大家聊聊有关java集合中ArrayList源码解析是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。整体架构ArrayList实
千家信息网最后更新 2026年11月03日java集合中ArrayList源码解析是怎样的
今天就跟大家聊聊有关java集合中ArrayList源码解析是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
整体架构
ArrayList实际就是个数组结构,如图

index:数组下标
elementData:数组本身
其他基本概念:
/** * Default initial capacity. * 数组初始大小 */ private static final int DEFAULT_CAPACITY = 10;
/** * The size of the ArrayList (the number of elements it contains). * 当前数组大小 * @serial */private int size;
//表示当前数组被修改的版本次数protected transient int modCount = 0;
类注释:
1、可以自动扩容
2、允许put null
3、size、set、put、add、get时间复杂度O(1)
4、非线程安全(作为共享变量时存在),必要时可以使用线程安全的SynchronizedList(性能低)
public boolean add(E e) { synchronized (mutex) {// synchronized 是一种轻量锁,mutex 表示一个当前 SynchronizedList return c.add(e); }}5、增强for循环或迭代时,若数组大小改变,则抛出异常
源码解析
一、初始化:
//1、指定大小初始化public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); }}//2、无参初始化 数组大小为空//初始化时数组大小不是默认的10,第一次add时扩容为10public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//3、指定初始数据初始化public ArrayList(Collection extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; }}二、新增、扩容、删除
新增:
public boolean add(E e) { //确保数组大小是否足够,不够执行扩容,size 为当前数组的大小 ensureCapacityInternal(size + 1); // Increments modCount!! //直接赋值,线程不安全的 elementData[size++] = e; 对null无校验,因此可以存入null值 return true;}扩容:
private void ensureCapacityInternal(int minCapacity) { //如果初始化数组大小时,有给定初始值,以给定的大小为准,不走 if 逻辑 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //确保容积足够 ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) { //记录数组被修改 modCount++; // 如果我们期望的最小容量大于目前数组的长度,那么就扩容 if (minCapacity - elementData.length > 0) grow(minCapacity);}//扩容,并把现有数据拷贝到新的数组里面去private void grow(int minCapacity) { int oldCapacity = elementData.length; // oldCapacity >> 1 是把 oldCapacity 除以 2 的意思 这里注意:ArrayList扩容是1+0.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果扩容后的值 < 我们的期望值,扩容后的值就等于我们的期望值 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 如果扩容后的值 > jvm 所能分配的数组的最大值,那么就用 Integer 的最大值 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); 扩容时源码中对上下数组大小做了校验,有很清晰的数组大小溢出意识,平时开发时应借鉴 // 通过复制进行扩容 elementData = Arrays.copyOf(elementData, newCapacity);}扩容动态图:
删除:
public boolean remove(Object o) { // 如果要删除的值是 null,找到第一个值是 null 的删除 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { 可以删除null值 fastRemove(index); return true; } } else { // 如果要删除的值不为 null,找到第一个和要删除的值相等的删除 for (int index = 0; index < size; index++) // 这里是根据 equals 来判断值相等的,相等后再根据索引位置进行删除 if (o.equals(elementData[index])) { //找到需要删除的索引 fastRemove(index); return true; } } return false;}//根据索引位置进行元素删除private void fastRemove(int index) { // 记录数组的结构要发生变动了 modCount++; // numMoved 表示删除 index 位置的元素后,需要从 index 后移动多少个元素到前面去 // 减 1 的原因,是因为 size 从 1 开始算起,index 从 0开始算起 int numMoved = size - index - 1; if (numMoved > 0) // 从 index +1 位置开始被拷贝,拷贝的起始位置是 index,长度是 numMoved System.arraycopy(elementData, index+1, elementData, index, numMoved); //数组最后一个位置赋值 null,帮助 GC elementData[--size] = null;}三、迭代器
implement java.util.Iterator
迭代器的一些参数:
int cursor;// 迭代过程中,下一个元素的位置,默认从 0 开始。
int lastRet = -1; // 新增场景:表示上一次迭代过程中,索引的位置;删除场景:为 -1。
int expectedModCount = modCount;// expectedModCount 表示迭代过程中,期望的版本号;modCount 表示数组实际的版本号。
迭代器源码分析:
//是否存在下一个可迭代的值public boolean hasNext() { return cursor != size;//cursor 表示下一个元素的位置,size 表示实际大小,如果两者相等,说明已经没有元素可以迭代了,如果不等,说明还可以迭代}//下一个可迭代的值public E next() { //迭代过程中,判断版本号有无被修改,有被修改,抛 ConcurrentModificationException 异常 checkForComodification(); //本次迭代过程中,元素的索引位置 int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); // 下一次迭代时,元素的位置,为下一次迭代做准备 cursor = i + 1; // 返回元素值 return (E) elementData[lastRet = i];}// 版本号比较final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException();}public void remove() { // 如果上一次操作时,数组的位置已经小于 0 了,说明数组已经被删除完了 if (lastRet < 0) throw new IllegalStateException(); //迭代过程中,判断版本号有无被修改,有被修改,抛 ConcurrentModificationException 异常 checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; // -1 表示元素已经被删除,这里也防止重复删除lastRet = -1; // 删除元素时 modCount 的值已经发生变化,在此赋值给 expectedModCount // 这样下次迭代时,两者的值是一致的了 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); }}看完上述内容,你们对java集合中ArrayList源码解析是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。
数组
迭代
大小
位置
元素
版本
过程
源码
期望
安全
内容
实际
拷贝
线程
最大
场景
数据
最大值
期望值
索引
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
中智农互联网科技
百单网互联网科技有限公司怎么样
广东万易互联网科技有限公司惠州分公司
互联网科技产业
科技互联网企业
华宇互联网科技
上海喔噻互联网科技
中国的互联网科技企业的崛起
和信科技工业互联网
互联网科技扶贫时间
亳州好赞互联网科技有限公司
烟台灵鸽互联网科技有限公司
深圳无忧互联网科技
黑云互联网科技有限公司
互联网科技年终奖
互联网安防科技感
互联网与数字科技关系
科技互联网经济论坛
广东猫王互联网科技有限公司电话
网互联网络科技
互联网与科技
互联网科技名片
新华互联网科技
安徽鑫晟辉互联网科技
互联网科技宣传片
科技与互联网哪个更好
互联网大会黑科技排名
苏州五指互联网络科技有限
互联网科技产业特征
上海互联网科技公司ppt