您好,登录后才能下订单哦!
# Java中ArrayList底层扩容原理以及扩容操作的示例分析
## 1. ArrayList概述
### 1.1 ArrayList简介
ArrayList是Java集合框架中最常用的动态数组实现,位于`java.util`包中。它基于数组实现,能够动态地增长和缩减容量,提供了快速随机访问的能力。
与普通数组相比,ArrayList具有以下优势:
- 自动扩容:无需手动处理数组扩容
- 丰富API:提供丰富的操作方法(add/remove/get等)
- 类型安全:通过泛型保证类型安全
### 1.2 核心特性
- **动态扩容**:当元素数量超过当前容量时自动扩容
- **非线程安全**:不适合多线程环境(可使用Vector或Collections.synchronizedList)
- **快速随机访问**:通过索引访问元素时间复杂度为O(1)
- **有序集合**:保持元素插入顺序
```java
// 基本使用示例
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
String item = list.get(0); // 随机访问
// JDK 1.8源码片段
transient Object[] elementData; // 实际存储元素的数组
private int size; // 当前元素数量
private static final int DEFAULT_CAPACITY = 10; // 默认初始容量
ArrayList本质上是对Object数组的封装,所有操作都基于这个数组: - 添加元素:向数组尾部插入 - 删除元素:需要移动后续元素 - 扩容操作:创建新数组并拷贝数据
// 构造方法源码分析
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");
}
}
当执行add操作时,会先检查容量:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 关键扩容检查
elementData[size++] = e;
return true;
}
ensureCapacityInternal()
grow()
Arrays.copyOf()
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
操作 | 平均时间复杂度 | 最坏情况 |
---|---|---|
add() | O(1) | O(n) |
add(index) | O(n) | O(n) |
get() | O(1) | O(1) |
每次扩容需要额外空间: - 临时新数组占用内存 - 旧数组等待GC回收
ArrayList(int initialCapacity)
addAll()
减少多次扩容public class ExpansionDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
// 打印扩容过程
for (int i = 0; i < 100; i++) {
System.out.printf("Size: %2d, Capacity: %2d%n",
list.size(), getCapacity(list));
list.add(i);
}
}
// 反射获取实际容量
static int getCapacity(ArrayList<?> list) {
try {
Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
return ((Object[]) field.get(list)).length;
} catch (Exception e) {
return -1;
}
}
}
输出结果示例:
Size: 0, Capacity: 0 // 初始空数组
Size: 1, Capacity: 10 // 首次插入扩容到10
...
Size: 10, Capacity: 10
Size: 11, Capacity: 15 // 第一次1.5倍扩容
...
Size: 15, Capacity: 15
Size: 16, Capacity: 22 // 第二次扩容
// 测试不同初始容量的性能差异
public static void testPerformance() {
final int COUNT = 1000000;
// 无初始容量
long start1 = System.nanoTime();
List<Integer> list1 = new ArrayList<>();
for (int i = 0; i < COUNT; i++) {
list1.add(i);
}
long time1 = System.nanoTime() - start1;
// 预分配容量
long start2 = System.nanoTime();
List<Integer> list2 = new ArrayList<>(COUNT);
for (int i = 0; i < COUNT; i++) {
list2.add(i);
}
long time2 = System.nanoTime() - start2;
System.out.printf("默认容量耗时:%.2fms%n", time1/1e6);
System.out.printf("预分配容量耗时:%.2fms%n", time2/1e6);
}
典型输出结果:
默认容量耗时:45.32ms
预分配容量耗时:12.67ms
当接近Integer.MAX_VALUE时:
// 测试最大容量
try {
List<Integer> hugeList = new ArrayList<>(Integer.MAX_VALUE);
} catch (OutOfMemoryError e) {
System.out.println("超出虚拟机内存限制");
}
// 并发修改异常示例
List<String> list = new ArrayList<>(Arrays.asList("A","B","C"));
for (String s : list) {
if ("B".equals(s)) {
list.remove(s); // 抛出ConcurrentModificationException
}
}
解决方案: 1. 使用Iterator的remove方法 2. 使用CopyOnWriteArrayList 3. 加同步锁
特性 | ArrayList | LinkedList |
---|---|---|
底层结构 | 动态数组 | 双向链表 |
随机访问 | O(1) | O(n) |
头部插入 | O(n) | O(1) |
内存占用 | 更小(连续内存) | 更大(节点开销) |
主要区别: 1. 线程安全:Vector方法同步 2. 扩容策略:Vector默认2倍扩容 3. 性能:ArrayList更高效
// 从已有集合创建
List
2. **批量操作**:
```java
// 优于循环add
list.addAll(Arrays.asList("a", "b", "c"));
内存敏感场景:
// 及时释放未用容量
list.trimToSize();
只读场景:
// 不可变列表
List<String> immutable = Collections.unmodifiableList(list);
ArrayList的扩容机制体现了空间换时间的设计思想: 1. 1.5倍平衡增长:避免频繁扩容又减少空间浪费 2. System.arraycopy优化:native方法实现高效数据迁移 3. fail-fast机制:通过modCount检测并发修改
理解扩容原理有助于: - 合理预估集合大小 - 优化内存使用 - 避免性能瓶颈 - 选择合适的集合类型
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。