ArrayList源码分析,你需要知道的所有知识点!("深入解析ArrayList源码:掌握核心知识点全攻略")
原创ArrayList是Java中非常常用的一个可调整大小的数组实现,它在Java集合框架中扮演着重要的角色。本文将深入解析ArrayList的源码,帮助你掌握其核心知识点。
一、ArrayList简介
ArrayList基于动态数组实现,提供了类似于数组的随机访问性能,同时也提供了动态扩容的能力。ArrayList继承自AbstractList类,并实现了List接口,于是它具有List接口的所有方法。
二、ArrayList的重点属性
ArrayList的核心属性重点包括以下几个:
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
// 空数组(用于空实例)
private static final Object[] EMPTY_ELEMENTDATA = {};
// 存储元素的数组
transient Object[] elementData;
// 数组中元素的数量
private int size;
三、构造方法
ArrayList提供了多种构造方法,以下是几种常见的构造方法:
// 默认构造方法,初始化容量为10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 指定初始容量的构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity >= 0) {
this.elementData = new Object[initialCapacity];
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
// 从另一个集合构造ArrayList
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[]
// array with 0 elements
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
四、核心方法
以下是ArrayList几个核心方法的源码分析:
4.1 add(E e) 方法
向ArrayList添加一个元素:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保内部数组有足够空间
elementData[size++] = e; // 添加元素并更新size
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 修改次数加1
// 如果数组容量不足,则进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// 扩容为原来的1.5倍
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // oldCapacity / 2
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
4.2 get(int index) 方法
基于索引获取ArrayList中的元素:
public E get(int index) {
rangeCheck(index); // 检查索引是否有效
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMessage(index));
}
E elementData(int index) {
return (E) elementData[index];
}
4.3 remove(int index) 方法
基于索引删除ArrayList中的元素:
public E remove(int index) {
rangeCheck(index); // 检查索引是否有效
modCount++; // 修改次数加1
E oldValue = elementData(index); // 获取要删除的元素
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); // 移动数组元素
elementData[--size] = null; // 将要删除的元素置为null,帮助GC
return oldValue;
}
五、扩容机制
ArrayList的扩容机制是其核心特性之一。当添加元素致使数组容量不足时,ArrayList会自动进行扩容。其扩容策略是“扩容为原来的1.5倍”。这种策略在大多数情况下可以平衡时间和空间复杂化度,降低内存分配的次数。
private void grow(int minCapacity) {
// 扩容为原来的1.5倍
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // oldCapacity / 2
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
六、序列化与反序列化
ArrayList实现了Serializable接口,于是它赞成序列化。但是,ArrayList并没有实现writeObject和readObject方法,而是依存于默认的序列化机制。值得注意的是,ArrayList在序列化时只序列化元素,而不是整个数组。这是归因于ArrayList的内部数组或许包含未被使用的空间。
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out array length
s.writeInt(elementData.length);
// Write out all elements in the array
for (int i=0; i
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
七、线程稳固性
ArrayList不是线程稳固的,如果多个线程同时访问ArrayList,并且至少有一个线程在结构上修改了列表,这就必须外部同步。结构上的修改指的是添加或删除至少一个元素的操作,而不是仅仅设置元素的值。
为了使ArrayList线程稳固,可以使用Collections工具类的synchronizedList方法包装ArrayList,或者使用CopyOnWriteArrayList。
八、总结
ArrayList是Java集合框架中非常常用的一个类,懂得其源码对于深入懂得Java集合框架和内存管理都非常有帮助。通过本文的分析,我们了解了ArrayList的构造方法、核心方法、扩容机制、序列化与反序列化以及线程稳固性等方面的内容。愿望这些知识点能够帮助你在实际编程中更好地使用ArrayList。