Java List 完全指南:从接口特性到四大实现类深度解析
一、介绍
List 是 Java 集合框架(java.util)中有序、可重复 的集合接口,继承自 Collection 接口,是日常开发中最常用的集合类型之一。其核心特征是:元素按插入顺序排列、允许重复元素、支持通过索引访问元素。
特性:
- 有序性:元素的存储顺序与插入顺序一致,可通过索引(0 开始)精准访问 / 修改元素。
- 可重复性 :允许添加多个相同的元素(
equals()返回 true 的元素)。 - 支持 null :允许存储 null 元素(不同实现类对 null 的支持略有差异,如
CopyOnWriteArrayList也支持,但Vector同样支持)。 - 索引操作 :提供大量基于索引的方法(如
get(int index)、set(int index, E element)),这是与Set最核心的区别。
二、List 接口核心方法
List 继承了 Collection 的所有方法,并扩展了索引相关的核心方法:
| 方法 | 作用 |
|---|---|
E get(int index) |
获取指定索引的元素 |
E set(int index, E element) |
替换指定索引的元素,返回原元素 |
void add(int index, E element) |
在指定索引插入元素,后续元素后移 |
E remove(int index) |
删除指定索引的元素,返回被删除元素 |
int indexOf(Object o) |
返回元素首次出现的索引,不存在则返回 -1 |
int lastIndexOf(Object o) |
返回元素最后出现的索引,不存在则返回 -1 |
List<E> subList(int fromIndex, int toIndex) |
截取子列表(左闭右开),注意:子列表是原列表的视图,修改会同步 |
ListIterator<E> listIterator() |
返回支持双向遍历的迭代器(可向前 / 向后遍历,还能添加 / 修改元素) |
三、List 主要实现类
Java 提供了多个 List 实现类,适配不同的业务场景,核心有以下 4 种:
1. ArrayList(最常用)
-
底层实现 :基于动态扩容的数组(初始容量 10,扩容时默认扩容 1.5 倍)。
补充:
ArrayList 的本质是可变长度的 Object 数组(JDK 8 及以上),所有元素都存储在这个数组中,数组的「固定长度」特性通过「扩容机制」被封装,对外表现为 "动态列表"。
java// ArrayList 核心底层数组(JDK 8 源码核心片段) public class ArrayList<E> extends AbstractList<E> implements List<E> { // 存储元素的底层数组(transient 表示不参与默认序列化) transient Object[] elementData; // 集合中实际元素的数量(≠ elementData.length) private int size; // 空数组常量(初始无参构造时使用) private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; }属性 作用 elementData核心存储数组,类型为 Object [],存放所有 ArrayList 元素;初始无参构造时,该数组为「空数组」(DEFAULTCAPACITY_EMPTY_ELEMENTDATA),首次添加元素时才初始化容量。 size记录集合中实际元素个数(而非数组长度),例如数组长度为 10 但只存了 3 个元素,size=3。 DEFAULT_CAPACITY默认初始容量(值为 10),首次添加元素时数组会扩容至 10。 MAX_ARRAY_SIZE数组最大容量(Integer.MAX_VALUE - 8),避免数组占用过多内存导致 OOM。 构造方法:
1.无参构造:
javaList<String> list = new ArrayList<>();2.指定初始容量构造
javaList<String> list = new ArrayList<>(20);3.基于集合构造
javaList<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));扩容:
调用
add()/addAll()时,若size + 新增元素数 > elementData.length,触发扩容。java// 1. 计算新容量:默认扩容1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 2. 若新容量不足(如新增大量元素),直接扩容至「所需最小容量」 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 3. 若新容量超过MAX_ARRAY_SIZE,修正为Integer.MAX_VALUE(避免溢出) if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 4. 拷贝原数组元素到新数组(核心:Arrays.copyOf) elementData = Arrays.copyOf(elementData, newCapacity); /* 扩容倍数:默认 1.5 倍(oldCapacity >> 1 等价于 oldCapacity/2); 扩容开销:扩容需要拷贝数组元素(System.arraycopy),属于 O (n) 操作,因此提前指定初始容量能减少扩容次数,提升性能; 空列表首次扩容:无参构造的 ArrayList 首次 add 时,直接将数组扩容至 10(而非 1.5 倍,因为初始数组长度为 0)。 */ -
核心特点:
- 随机访问快(数组索引直接访问,时间复杂度 O (1));
- 插入 / 删除慢(需移动元素,时间复杂度 O (n));
- 非线程安全 (多线程操作会抛出
ConcurrentModificationException); - 支持快速随机遍历,适合读多写少的场景。
-
使用示例:
java
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
String first = arrayList.get(0); // 获取第一个元素
arrayList.set(1, "C++"); // 替换第二个元素
2. LinkedList
-
底层实现 :基于双向链表(每个节点存储前驱、后继和元素)。
补充:
LinkedList 的本质是双向循环链表(逻辑上)/ 双向非循环链表(物理实现),每个元素封装为「节点(Node)」,节点间通过前驱 / 后继指针相连,整体无固定长度的数组,而是通过指针动态拼接。
java// 私有静态内部类:链表的最小单元 private static class Node<E> { E item; // 节点存储的元素 Node<E> next; // 指向后继节点的指针(下一个节点) Node<E> prev; // 指向前驱节点的指针(上一个节点) // 节点构造器:初始化前驱、元素、后继 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }属性:
javapublic class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E> { transient int size = 0; // 链表中实际元素个数 transient Node<E> first; // 指向链表头节点的指针 transient Node<E> last; // 指向链表尾节点的指针 }属性 作用 first头节点指针:若链表为空, first = null;否则指向第一个节点(prev = null)。last尾节点指针:若链表为空, last = null;否则指向最后一个节点(next = null)。size记录节点总数,避免遍历计数(O (1) 获取长度)。 结构示意:
null ← [prev|item1|next] ↔ [prev|item2|next] ↔ [prev|item3|next] → null ↑(first) ↑(last)- 头节点:
prev = null,next指向第二个节点; - 尾节点:
next = null,prev指向倒数第二个节点; - 中间节点:
prev指向前一个,next指向后一个; - 空链表:
first = last = null,size = 0。
构造方法(两种):
1.无参构造:
javaList<String> list = new LinkedList<>();2.基于集合构造:
javaList<String> list = new LinkedList<>(Arrays.asList("a", "b", "c")); - 头节点:
-
核心特点:
- 随机访问慢(需遍历链表,时间复杂度 O (n));
- 首尾插入 / 删除快(无需移动元素,时间复杂度 O (1));
- 非线程安全;
- 实现了
Deque接口,可作为队列 / 双端队列使用; - 适合写多读少、频繁增删的场景。
-
使用示例:
java
List<String> linkedList = new LinkedList<>();
linkedList.addFirst("A"); // 头部添加
linkedList.addLast("B"); // 尾部添加
linkedList.removeFirst(); // 删除头部
3. Vector(古老的线程安全实现)
-
底层实现 :基于数组,与 ArrayList 类似,但方法加了 synchronized 锁。
补充:
Vector 的本质是线程安全的动态扩容数组 ,与 ArrayList 一样,所有元素存储在 Object 数组中,核心区别是:Vector 的核心方法通过
synchronized修饰实现线程安全,扩容倍数和初始化逻辑也不同。javapublic class Vector<E> extends AbstractList<E> implements List<E> { // 存储元素的底层数组(与 ArrayList 的 elementData 一致) protected Object[] elementData; // 集合中实际元素个数(与 ArrayList 的 size 一致) protected int elementCount; // 扩容增量(可选:指定扩容时每次增加的容量,默认0) protected int capacityIncrement; // 序列化版本号(ArrayList 也有,仅序列化用) private static final long serialVersionUID = -2767605614048989439L; }属性 作用 与 ArrayList 对比 elementData核心存储数组,类型为 Object [] 完全一致(ArrayList 用 transient 修饰,Vector 用 protected 修饰) elementCount实际元素个数(等价于 ArrayList 的 size) 命名不同,功能完全一致 capacityIncrement扩容增量:1. 若 > 0,扩容时数组长度 += 该值;2. 若 ≤ 0,扩容时数组长度翻倍(默认 0) ArrayList 无此属性,固定扩容 1.5 倍 DEFAULT_CAPACITY默认初始容量(值为 10) 与 ArrayList 一致,但初始化逻辑不同 构造方法(四种):
1.无参构造
javaVector<String> vector = new Vector<>();2.指定初始容量构造
javaVector<String> vector = new Vector<>(20);3.指定初始容量 + 扩容增量构造
javaVector<String> vector = new Vector<>(20, 5);4.基于集合构造
javaVector<String> vector = new Vector<>(Arrays.asList("a", "b", "c"));扩容:
调用
add()/addAll()时,若elementCount + 新增元素数 > elementData.length,触发扩容。java// 1. 计算新容量 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); // 2. 若新容量不足(如新增大量元素),直接扩容至所需最小容量 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 3. 拷贝原数组元素到新数组(与 ArrayList 一致,用 Arrays.copyOf) elementData = Arrays.copyOf(elementData, newCapacity); /* 扩容倍数规则: 若 capacityIncrement > 0:扩容后容量 = 原容量 + capacityIncrement(如初始 20、增量 5,扩容后 25); 若 capacityIncrement ≤ 0:扩容后容量 = 原容量 × 2(默认翻倍,ArrayList 是 1.5 倍); 扩容开销:与 ArrayList 一致,扩容需拷贝数组(O (n) 操作),且翻倍扩容比 1.5 倍更易造成内存浪费; 示例: 无参构造的 Vector(初始 10,增量 0):首次扩容至 20,第二次至 40,第三次至 80... 指定增量 5 的 Vector(初始 20):首次扩容至 25,第二次至 30,第三次至 35... */ -
核心特点:
- 线程安全(但锁粒度大,性能差);
- 扩容默认 2 倍(ArrayList 1.5 倍);
- 基本被
CopyOnWriteArrayList替代,仅兼容旧代码时使用。
4. CopyOnWriteArrayList(并发安全)
-
底层实现 :基于写时复制数组(修改操作会复制一份新数组,修改后替换原数组)。
补充:
CopyOnWriteArrayList 的本质是 "只读原数组 + 写时复制新数组" 的动态数组结构,核心设计思想:
- 读操作直接访问「不可变的原数组」,无需加锁,性能极高;
- 写操作(增 / 删 / 改)先复制一份新数组,在新数组上完成修改,再替换原数组,全程加锁保证线程安全;
- 所有数组操作均基于「不可变数组」,天然避免了并发修改异常(
ConcurrentModificationException)。
javapublic class CopyOnWriteArrayList<E> implements List<E>, RandomAccess { // 全局锁:仅用于写操作(add/remove/set),读操作无锁 final transient ReentrantLock lock = new ReentrantLock(); // 存储元素的底层数组(volatile 修饰,保证多线程可见性) private transient volatile Object[] array; // 获取当前数组(核心内部方法) final Object[] getArray() { return array; } // 替换数组(仅写操作后调用) final void setArray(Object[] a) { array = a; } }属性 作用 核心设计考量 lock可重入锁(ReentrantLock) 仅锁定写操作,保证同一时间只有一个线程执行 "复制数组 + 修改",避免多线程写冲突;读操作完全无锁。 array存储元素的核心数组(volatile 修饰) 1. volatile保证数组引用的可见性:修改后新数组的引用能立即被其他线程感知;2. 数组本身是 "不可变" 的:读操作期间数组不会被修改,无需担心并发问题。构造方法:
1.无参构造
javaCopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();2.基于集合构造
javaCopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));写时复制原理:
1.读操作(无锁 + O (1) 高效)
读操作(
get()/iterator()/contains()等)全程无锁,直接访问当前array数组,无需担心并发修改:java// get(int index):无锁,直接索引访问 public E get(int index) { return elementAt(getArray(), index); // getArray() 返回当前 array,elementAt 等价于 (E) array[index] } // 迭代器:基于当前数组创建"快照迭代器",遍历期间原数组修改不影响迭代结果 public Iterator<E> iterator() { return new COWIterator<>(getArray(), 0); // 传入当前数组的副本,迭代器仅遍历该副本 }- 核心优势:读操作无锁、无阻塞,即使写操作正在执行,读操作仍访问旧数组,不会抛出
ConcurrentModificationException; - 小缺点:读操作可能读取到 "旧数据"(最终一致性),适合对数据实时性要求不高、读多写少的场景(如配置缓存)。
2.写操作(加锁 + 复制数组 + O (n) 开销)
所有写操作(
add()/remove()/set())都遵循「加锁 → 复制原数组 → 修改新数组 → 替换原数组 → 解锁」的流程,核心是 "不修改原数组,仅修改副本"。写操作中的部分细节介绍:
- 锁粒度:仅写操作加锁,读操作不受影响,相比 Vector 的 "方法级 synchronized",并发性能提升极大;
- 数组复制开销:写操作需拷贝整个数组(O (n) 时间复杂度),写频率越高,性能越差,因此仅适合 "读多写少" 场景;
- 内存占用:写操作期间会同时存在原数组和新数组两份内存,内存开销较大(如原数组 100 万元素,写时需额外占用 100 万元素的内存);
- 数据一致性 :写操作的结果需等
setArray()后才对其他线程可见,读操作可能读取到修改前的旧数据(最终一致性,非强一致性)。
(1)新增操作(add (E e)):
javapublic boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); // 1. 加锁,独占写操作 try { Object[] elements = getArray(); // 2. 获取当前原数组 int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); // 3. 复制新数组(长度+1) newElements[len] = e; // 4. 在新数组尾部添加元素 setArray(newElements); // 5. 替换原数组(volatile 保证可见性) return true; } finally { lock.unlock(); // 6. 解锁,释放锁 } }(2)删除操作(remove (int index)):
javapublic E remove(int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; E oldValue = elementAt(elements, index); // 暂存被删除元素 int numMoved = len - index - 1; Object[] newElements; if (numMoved == 0) { // 删除最后一个元素:复制长度-1的新数组 newElements = Arrays.copyOf(elements, len - 1); } else { // 删除中间元素:分两段拷贝(前半段 + 后半段) newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); } setArray(newElements); // 替换原数组 return oldValue; } finally { lock.unlock(); } }(3)修改操作(set (int index, E element)):
javapublic E set(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); E oldValue = elementAt(elements, index); if (oldValue != element) { // 元素不同才复制修改 int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); // 复制等长新数组 newElements[index] = element; // 修改新数组指定位置 setArray(newElements); } else { // 元素相同,无需修改,直接返回(避免无意义的数组复制) setArray(elements); } return oldValue; } finally { lock.unlock(); } } -
核心特点:
- 线程安全(读操作无锁,写操作加锁但不阻塞读);
- 读性能极高,写性能较低(复制数组开销大);
- 迭代器是 "快照",不会抛出
ConcurrentModificationException; - 适合读多写少的并发场景(如配置缓存、日志收集)。
-
使用示例:
java
List<String> cowList = new CopyOnWriteArrayList<>();
cowList.add("a");
cowList.add("b");
// 多线程遍历无需加锁
for (String s : cowList) {
System.out.println(s);
}
四、List 常见使用场景
| 场景 | 推荐实现类 |
|---|---|
| 日常开发、读多写少、随机访问 | ArrayList |
| 频繁增删(尤其是首尾)、队列 / 栈场景 | LinkedList |
| 多线程并发、读多写少 | CopyOnWriteArrayList |
| 旧代码兼容、低并发线程安全 | Vector |
五、注意事项
-
subList 陷阱:
subList()返回的是原列表的视图,修改子列表会同步修改原列表,且子列表生命周期依赖原列表(原列表结构修改后,子列表操作会抛异常)。
javaList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3)); List<Integer> sub = list.subList(0,2); sub.add(4); // 原列表变为 [1,2,4,3] list.clear(); // 原列表清空后,sub.get(0) 会抛异常 -
迭代器遍历:
遍历 List 时,若需删除元素,需使用ListIterator的remove()方法,而非for循环(否则抛ConcurrentModificationException)。
javaList<String> list = new ArrayList<>(Arrays.asList("a","b","c")); ListIterator<String> it = list.listIterator(); while (it.hasNext()) { if (it.next().equals("b")) { it.remove(); // 安全删除 } } -
空值处理 :List 允许存储 null,但实际开发中应尽量避免(容易导致
NullPointerException,且部分场景如排序会报错)。 -
线程安全 :ArrayList/LinkedList 非线程安全,多线程修改时需手动加锁(如
Collections.synchronizedList()),或直接使用 CopyOnWriteArrayList。
六、总结
List 是 Java 中有序可重复的集合,核心实现类各有侧重:
- ArrayList:性能均衡,适合大多数场景;
- LinkedList:适合频繁增删的场景;
- CopyOnWriteArrayList:适合并发读多写少的场景;
- Vector:尽量避免使用,仅兼容旧代码。
选择时需根据 "访问效率、修改频率、并发场景" 三大维度权衡。
附表:
| JDK 版本 | List 接口核心变更 | ArrayList 关键变更 | LinkedList 关键变更 | Vector 关键变更 | CopyOnWriteArrayList 关键变更 |
|---|---|---|---|---|---|
| JDK 1.2 | 1. 正式引入 List 接口,继承 Collection,定义核心索引方法(get/set/add(int, E)/remove(int) 等);2. 同时引入 ArrayList、LinkedList、Vector 实现类;3. Vector 作为早期线程安全实现,方法已加 synchronized。 |
1. 初始版本基于动态数组实现,默认初始容量 10;2. 扩容逻辑为「按需扩容」,早期扩容倍数不固定(后续 JDK 1.4 定型为 1.5 倍);3. 无 trimToSize() 之外的内存优化方法。 |
1. 基于双向链表实现,实现 List 接口但未实现 Deque;2. 仅提供基础的增删改查方法,无 addFirst/addLast 等队列方法(后续 JDK 1.6 补充)。 |
1. 初始版本即线程安全(方法加 synchronized);2. 扩容默认翻倍(capacityIncrement 默认为 0);3. 核心属性 elementData 为 protected 修饰。 |
未引入(属于并发包,JDK 1.5 才加入) |
| JDK 1.3 | 无接口层面变更,仅优化集合框架的内部迭代器实现,减少 ConcurrentModificationException 触发概率。 |
优化数组拷贝逻辑,引入 System.arraycopy 替代原生循环拷贝,提升扩容性能。 |
优化链表节点的内存布局,减少空指针异常风险;新增 indexOf/lastIndexOf 方法的遍历优化。 |
无核心变更,仅修复少量线程安全漏洞(如扩容时的竞态条件)。 | 未引入 |
| JDK 1.4 | 1. 新增 ListIterator 接口,支持双向遍历、添加 / 修改元素;2. List 接口新增 listIterator() 方法;3. 完善 subList() 方法规范,明确子列表为原列表视图。 |
1. 定型扩容逻辑:默认扩容 1.5 倍(oldCapacity + (oldCapacity >> 1));2. 新增 ensureCapacity(int) 方法,支持手动预扩容;3. 修复 subList 视图修改导致的数组越界问题。 |
1. 实现 ListIterator 接口,支持双向迭代;2. 优化链表遍历性能,减少节点指针遍历开销。 |
1. 新增 isEmpty() 方法的优化(直接判断 elementCount == 0);2. 对齐 ArrayList 的 trimToSize() 方法。 |
未引入 |
| JDK 1.5 | 1. 引入泛型(Generic),List 接口支持类型参数(List<E>),解决原始类型的类型安全问题;2. 新增 Collections.synchronizedList(List) 工具方法,为非线程安全 List 提供线程安全包装。 |
1. 全面支持泛型,替换所有 Object 强转,避免类型转换异常;2. 优化空列表初始化(引入空数组常量,减少内存占用)。 |
1. 支持泛型,节点 Node 改为泛型类型(Node<E>);2. 新增 offer/peek/poll 等队列方法(初步兼容队列特性)。 |
1. 支持泛型;2. 性能优化:减少 synchronized 锁的不必要开销。 |
1. 首次引入(位于 java.util.concurrent 包);2. 基于写时复制(COW)实现,支持基本的增删改查;3. 初始版本已实现 RandomAccess 接口,支持随机访问。 |
| JDK 1.6 | 1. List 接口新增 toArray(T[] a) 重载方法,支持指定类型数组返回;2. LinkedList 实现 Deque 接口,扩展队列 / 双端队列能力。 |
1. 优化 addAll 方法的扩容逻辑,减少多次扩容;2. 修复迭代器遍历期间的并发修改异常(fast-fail 机制优化)。 |
1. 实现 Deque 接口,新增 addFirst/addLast/removeFirst/removeLast 等方法;2. 优化链表首尾操作性能(直接通过 first/last 指针访问,无需遍历)。 |
1. 新增 copyInto(Object[]) 方法的重载;2. 标记为「低效线程安全实现」,官方推荐优先使用 CopyOnWriteArrayList。 |
1. 优化写操作的锁粒度(使用 ReentrantLock 替代 synchronized);2. 新增 iterator() 快照迭代器,避免并发修改异常。 |
| JDK 1.7 | 无接口层面核心变更,仅优化集合框架的内存占用。 | 1. 移除 elementData 中的多余空数组常量,减少内存浪费;2. 优化 trimToSize() 方法,避免不必要的数组拷贝。 |
优化链表节点的创建逻辑,减少对象创建开销;修复空链表操作时的空指针异常。 | 无核心变更,仅维护性修复。 | 1. 优化数组复制逻辑,使用 Arrays.copyOf 替代手动循环;2. 修复写操作时的内存溢出问题(新增 MAX_ARRAY_SIZE 限制)。 |
| JDK 1.8 | 1. 引入 Stream API,List 可通过 stream()/parallelStream() 实现流式操作;2. 新增 forEach(Consumer) 方法,支持函数式遍历;3. 新增 replaceAll(UnaryOperator)、sort(Comparator) 方法。 |
1. 实现 forEach/replaceAll/sort 方法,适配函数式编程;2. 优化 stream() 遍历性能,减少迭代器创建开销;3. 无参构造时,elementData 初始化为空数组(延迟扩容至首次 add 时的 10)。 |
1. 适配 Stream API 和函数式方法;2. 优化 sort 方法,先转为数组排序再重建链表(提升排序性能)。 |
1. 适配函数式方法(forEach/replaceAll);2. 官方文档明确标注「过时推荐使用 CopyOnWriteArrayList」。 |
1. 适配 Stream API 和函数式遍历;2. 优化读操作的可见性(array 数组保持 volatile 修饰);3. 减少写操作时的无意义数组复制(如 set 方法判断元素是否相同)。 |
| JDK 9 | 1. 新增 List.of() 静态工厂方法,创建不可变 List(元素不可增删改,不支持 null);2. 新增 List.copyOf() 方法,复制现有集合为不可变 List。 |
无核心实现变更,仅兼容 List.copyOf() 方法(返回不可变 ArrayList 视图)。 |
无核心变更,List.copyOf() 对 LinkedList 复制时转为不可变数组实现。 |
无核心变更,List.copyOf() 不推荐用于 Vector。 |
1. 兼容 List.copyOf() 方法,返回不可变副本;2. 优化锁的公平性,减少写操作的锁竞争。 |
| JDK 10+ | 1. 不可变 List 进一步优化(减少内存占用,提升遍历性能);2. 修复 subList() 视图在并发场景下的异常。 |
1. 优化内存布局,使用压缩指针减少 elementData 数组的内存开销;2. 修复扩容时的整数溢出问题(hugeCapacity 方法优化)。 |
优化链表节点的 GC 回收效率,减少内存泄漏风险。 | 仅维护性修复,无功能增强。 | 1. 优化写操作的数组复制性能(引入 JVM 层面的数组拷贝优化);2. 修复迭代器快照的一致性问题。 |