ArrayList源码分析,你需要知道的所有知识点!("深入解析ArrayList源码:你需要掌握的核心知识点全览!")
原创
一、ArrayList简介
ArrayList是基于动态数组的数据结构,实现了List接口,允许包含重复元素和null值。ArrayList提供了动态数组的灵活性和数组的随机访问性能,是Java集合框架中使用最广泛的类之一。
二、ArrayList的核心构造方法
ArrayList提供了多个构造方法,以下是三种常用的构造方法:
public ArrayList(int initialCapacity) {
if (initialCapacity >= 0) {
this.elementData = new Object[initialCapacity];
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[]
// array with a length consistent with the collection size.
// Adjust array size if necessary
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
三、ArrayList的核心成员变量
ArrayList中几个重要的成员变量如下:
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // 非私有变量,用于存储数组元素
private int size; // 数组实际存储的元素个数
四、ArrayList的扩容机制
ArrayList的扩容机制是它的核心特性之一。当数组空间不足以容纳更多元素时,会自动进行扩容。以下是扩容的核心代码:
private void ensureExplicitCapacity(int minCapacity) {
if (minCapacity > elementData.length) {
grow(minCapacity);
}
}
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);
}
五、ArrayList的添加元素方法
ArrayList提供了多种添加元素的方法,以下是一些常用的方法:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
六、ArrayList的删除元素方法
ArrayList提供了删除元素的方法,以下是删除方法的核心实现:
public E remove(int index) {
if (index >= size || index < 0) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++) {
if (elementData[index] == null) {
fastRemove(index);
return true;
}
}
} else {
for (int index = 0; index < size; index++) {
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
elementData[--size] = null; // clear to let GC do its work
}
七、ArrayList的遍历方法
ArrayList拥护多种遍历对策,以下是两种常用的遍历方法:
// 通过for循环遍历
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 处理元素
}
// 通过迭代器遍历
Iterator
it = list.iterator(); while (it.hasNext()) {
E element = it.next();
// 处理元素
}
八、ArrayList的性能分析
ArrayList的性能特点如下:
- 随机访问性能优异,时间纷乱度为O(1)。
- 添加和删除元素在数组末尾的时间纷乱度为O(1),但在数组中间的时间纷乱度为O(n)。
- 扩容操作的时间纷乱度为O(n)。
九、ArrayList的线程保险性
ArrayList是非线程保险的,如果多个线程同时访问ArrayList,必须进行同步处理。可以使用Collections工具类的synchronizedList方法来包装ArrayList,或者使用Vector代替ArrayList。
List
synchronizedList = Collections.synchronizedList(new ArrayList<>());
十、总结
ArrayList是Java集合框架中非常重要的一部分,懂得其源码和内部机制对于Java开发者来说至关重要。通过本文的分析,我们了解了ArrayList的核心构造方法、成员变量、扩容机制、添加和删除元素的方法、性能特点以及线程保险性。掌握这些知识点,可以帮助我们更好地使用ArrayList,优化程序性能,避免潜在的问题。