Java ArrayList 源码深度解析:揭秘数组背后的奥秘

在Java编程语言中,ArrayList是一个非常实用的集合类,它基于动态数组实现,可以动态地调整容量,支持元素的增删改查。在Java开发中,ArrayList被广泛使用,但很多人对它的内部实现并不了解。本文将深入剖析Java ArrayList的源码,帮助大家更好地理解其工作原理。
一、ArrayList简介
ArrayList是Java集合框架中的一个类,属于List接口的实现。它是一个可调整大小的数组实现,在内部使用一个动态数组来存储元素。ArrayList具有以下特点:
1. 顺序访问:ArrayList按照元素的添加顺序进行访问,即元素按照从0到size-1的索引顺序排列。
2. 动态数组:ArrayList在内部使用一个动态数组来存储元素,当数组容量不足时,会自动扩容。
3. 可调整大小:ArrayList可以根据需要动态调整其容量。
4. 支持随机访问:ArrayList支持随机访问,即可以通过索引直接访问指定位置的元素。
二、ArrayList源码解析
1. 内部实现
ArrayList在内部使用一个动态数组来存储元素,该数组在类中定义为一个名为elementData的变量。elementData是一个Object类型的数组,用于存储ArrayList中的元素。
```java
private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData;
private int size;
```
2. 构造方法
ArrayList提供了多个构造方法,允许用户指定初始容量和默认容量。
```java
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ARRAY;
}
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ARRAY;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class) {
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
} else {
this.elementData = EMPTY_ARRAY;
}
}
```
3. 自动扩容
当向ArrayList添加元素时,如果当前数组容量不足,ArrayList会自动扩容。以下是自动扩容的方法:
```java
public void add(E e) {
modCount++;
int oldCapacity = elementData.length;
if (size == oldCapacity) {
int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
elementData = Arrays.copyOf(elementData, newCapacity);
}
elementData[size++] = e;
}
```
在这个方法中,首先获取当前数组的长度,然后判断是否需要扩容。如果需要扩容,则计算新的容量,并使用Arrays.copyOf方法将旧数组复制到新的数组中。
4. 索引访问
ArrayList支持通过索引访问元素,以下是索引访问的方法:
```java
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
```
这两个方法分别用于获取和设置指定索引位置的元素。在设置元素之前,先检查索引是否有效,然后使用elementData(index)获取数组中指定索引位置的元素。
三、总结
通过以上分析,我们可以了解到ArrayList的内部实现原理。它基于动态数组实现,支持动态扩容,可以高效地进行元素的添加、删除、修改和访问。掌握ArrayList的源码,有助于我们更好地理解其工作原理,从而在Java开发中更好地运用它。
在实际开发中,我们应该根据实际需求选择合适的集合类。当需要快速随机访问元素时,ArrayList是一个不错的选择。但如果需要频繁地进行插入和删除操作,可能需要考虑其他集合类,如LinkedList。总之,了解ArrayList的源码,有助于我们更好地掌握Java集合框架。





