目录
一、ArrayList概述
二、优缺点分析
三、底层数据结构
四、源码分析ArrayList初始化容量
五、源码分析ArrayList扩容策略
六、ArrayList集合源码分析
1. 属性分析
2. 构造方法分析
无参构造方法
指定初始容量的构造方法
传入集合的构造方法
3. 添加元素
add(E e) 方法
add(int index, E element) 方法
4. 修改元素
set(int index, E element) 方法
5. 插入元素
6. 删除元素
remove(int index) 方法
remove(Object o) 方法
七、Vector
1. 底层结构与线程安全
2. 初始容量与扩容策略
3. 为何逐渐被弃用?
一、ArrayList概述
ArrayList 是Java集合框架中最常用的类之一,基于动态数组实现,继承自 AbstractList
并实现了 List
接口。它提供了高效的元素访问能力,适合频繁查询但少随机增删的场景。本文将从源码层面深入分析其设计原理、性能特点及最佳实践。
二、优缺点分析
优点:
高效随机访问:通过下标直接访问元素,底层是数组,因此根据下标查找元素的时间复杂度是O(1)。因此检索效率高。
list.get(3); // 直接访问索引3处的元素
尾部操作高效:在数组末尾添加或删除元素时,时间复杂度为 O(1)(无需移动元素)。
缺点:
随机增删效率低:在数组中间插入或删除元素时,需移动后续元素,时间复杂度为 O(n)。不过只要数组的容量还没满,对末尾元素进行增删,效率不受影响
list.add(2, "Java"); // 插入到索引2,后续元素后移
内存浪费:数组容量可能大于实际元素数量,占用额外内存
三、底层数据结构
ArrayList 的核心是一个 Object[] elementData
数组,所有元素按插入顺序依次存储。数组的连续内存特性使得其支持通过下标快速访问元素(时间复杂度 O(1)
)。
// JDK 11源码片段
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
transient Object[] elementData; // 存储元素的数组
private int size; // 实际元素个数
}
四、源码分析ArrayList初始化容量
在 Java 中,ArrayList
类有多个构造方法,不同构造方法对初始容量的处理不同:
- 无参构造方法:初始容量为 0,当第一次调用
add
方法时,容量会被初始化为 10。 - 带初始容量参数的构造方法:使用指定的初始容量。
- 带集合参数的构造方法:初始容量为传入集合的大小。
下面是 ArrayList
无参构造方法的源码:
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
其中 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
是一个空数组:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
无参构造:创建一个空数组(初始容量为0),首次调用 add()
方法时扩容至 10。
List<String> list = new ArrayList<>(); // elementData = {}
list.add("A"); // 首次扩容,容量变为10
当第一次调用 add
方法时,会触发扩容逻辑,将容量初始化为 10,相关源码如下:
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
其中 DEFAULT_CAPACITY
的值为 10:
private static final int DEFAULT_CAPACITY = 10;
五、源码分析ArrayList扩容策略
-
触发条件:当元素数量
size
超过数组长度elementData.length
。 -
扩容规则:新容量为原容量的 1.5倍(通过位运算优化:
newCapacity = oldCapacity + (oldCapacity >> 1)
)。 -
扩容实现:调用
Arrays.copyOf()
创建新数组并拷贝原数据。