Java ArrayList 源码深度剖析:揭秘数组扩容与遍历机制

正文内容:
在Java编程语言中,ArrayList是使用非常广泛的一个集合类,它实现了List接口,底层使用数组来存储元素。ArrayList具有很好的性能和灵活性,是Java集合框架中的基础类之一。本文将从ArrayList的源码出发,深入剖析其实现原理,包括数组扩容和遍历机制等细节。
一、ArrayList概述
ArrayList在Java中属于泛型集合,可以存储任意类型的对象。它的构造方法有多个,可以根据实际需求创建不同容量的ArrayList。下面是ArrayList的基本属性:
1. 元素存储:使用Object类型的数组存储元素,默认初始容量为10。
2. 容量:ArrayList的实际容量,即数组长度。
3. 元素数量:ArrayList中存储的元素个数。
4. 扩容机制:当数组容量不足时,会进行扩容操作。
5. 遍历机制:支持迭代器遍历,也可以使用for循环进行遍历。
二、ArrayList源码解析
1. 构造方法
```java
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
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);
}
}
public ArrayList(int initialCapacity, int loadFactor) {
if (initialCapacity <= 0 || loadFactor <= 0 || loadFactor > 1) {
throw new IllegalArgumentException("Illegal arguments");
}
this.loadFactor = loadFactor;
this.elementData = new Object[initialCapacity];
}
```
ArrayList提供了三个构造方法,分别用于创建不同初始容量的ArrayList。
2. 扩容机制
当向ArrayList添加元素时,如果数组容量不足,会进行扩容操作。扩容操作的具体步骤如下:
```java
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 加上原容量的1/2
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
```
首先,判断数组容量是否满足需求。如果不满足,将原容量乘以1.5,然后与minCapacity进行比较。如果仍不满足,则取minCapacity与MAX_ARRAY_SIZE中较小的值作为新容量。最后,使用Arrays.copyOf方法将原数组复制到新数组中。
3. 遍历机制
ArrayList支持两种遍历方式:迭代器遍历和for循环遍历。
迭代器遍历:
```java
Iterator
return new Itr();
}
private class Itr implements Iterator
int cursor; // 游标
int lastRet = -1; // 上次返回的元素索引
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
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];
}
public void remove() {
checkForComodification();
int lastRet = this.lastRet;
if (lastRet == -1)
throw new IllegalStateException();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
```
for循环遍历:
```java
for (int i = 0; i < size; i++) {
// ...
}
```
总结
通过对ArrayList源码的剖析,我们可以了解到ArrayList在内存存储、扩容和遍历方面的实现细节。了解这些细节有助于我们更好地利用ArrayList,提高程序性能。在实际开发过程中,合理运用ArrayList的特性,可以有效提高代码质量。






