ArrayList源码分析
- 属性解释
- 构造器
- API
- 1 boolean add(E e) 添加元素
- 2 void add(int index, E element) 添加元素指定位置
- 3 boolean addAll(Collection<? extends E> c) 添加集合
- 4 trimToSize() 将当前数组容量设置为元素的长度
- 5 ensureCapacity(int minCapacity) 确保容量
- 6 size() 获取数组元素的个数
- 7 isEmpty() 判断是否为空
- 8 indexOfRange()查找元素
- 9 contains 判断是否包含元素
- 10 indexOf()正向查找
- 11 lastIndexOf()逆向查找
- 12 clone
- 13 Object[] toArray() 转化为数组
- 14 get(int index) 获取元素
- 15 remove(int index) 删除指定位置元素
所有的分析基于JDK15
ArrayList的数据结构是数组。基于数组的实现。是线程不安全的数据结构。实现了List接口。
属性解释
//默认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() 构造一个初始容量为10的空列表。
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。
ArrayList(Collection<? extends E> c) 构造一个列表,该列表包含指定集合的元素,其顺序由集合的迭代器返回。
API
1 boolean add(E e) 添加元素
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
modCount是ArrayList的父类AbstractList的属性。主要目的是在迭代器iterator在迭代集合的时候不允许对集合结构做修改,如果做了修改,就会报并发修改异常。后续详解。
add的添加在内部方法add(e, elementData, size);中完成。
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
如果元素个数和数组长度相等,就扩容,否则就直接添加元素。数组元素长度+1.来看下扩容的实现,调用grow()方法。
private Object[] grow() {
return grow(size + 1);
}
也是私有的,内部调用grow(int minCapacity)实现。参数是当前容量+1。
private Object[] grow(int minCapacity) {
// 获取旧数组的长度
int oldCapacity = elementData.length;
//如果旧数组容量>0 或者不为空数组。就开始扩容
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
如果是空数组,就返回最小容量和默认容量最大值的数组。
elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)
新的容量:
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1
调用ArraysSupport.newLength方法实现。
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
if (newLength - MAX_ARRAY_LENGTH <= 0) {
return newLength;
}
return hugeLength(oldLength, minGrowth);
}
这里的prefGrowth为首选增长率,minGrowth为最小增长率。
minGrowth=minCapacity - oldCapacity
prefGrowth=oldCapacity>>1=0.5oldCapacity.因此实际扩容后的长度为1.5倍的原数组长度。最后进行了数组复制。
elementData = Arrays.copyOf(elementData, newCapacity);
2 void add(int index, E element) 添加元素指定位置
public void add(int index, E element) {
//检查索引是否超过数组长度
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
首先检查是否索引越界,然后判断如果元素的数量和数组长度相等,进入逻辑。扩容,然后复制旧的数据,然后赋值操作。
3 boolean addAll(Collection<? extends E> c) 添加集合
public boolean addAll(Collection<? extends E> c) {
//将集合转换为Object数组
Object[] a = c.toArray();
modCount++;
int numNew = a.length;
if (numNew == 0)
return false;
Object[] elementData;
final int s;
//如果添加元素的长度大于剩余数组的容量,开始扩容。然后复制数据
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
System.arraycopy(a, 0, elementData, s, numNew);
size = s + numNew;
return true;
}
4 trimToSize() 将当前数组容量设置为元素的长度
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
5 ensureCapacity(int minCapacity) 确保容量
若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=newLength = Math.max(最小容量-旧数组容量, 旧数组容量/2) + 旧数组容量=1.5旧数组容量
public void ensureCapacity(int minCapacity) {
if (minCapacity > elementData.length
&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
&& minCapacity <= DEFAULT_CAPACITY)) {
modCount++;
grow(minCapacity);
}
}
6 size() 获取数组元素的个数
public int size() {
return size;
}
7 isEmpty() 判断是否为空
public boolean isEmpty() {
return size == 0;
}
8 indexOfRange()查找元素
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
//如果为空,正向遍历
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
//不为空,直接遍历
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
9 contains 判断是否包含元素
public boolean contains(Object o) {
//调用index()方法正向查找
return indexOf(o) >= 0;
}
10 indexOf()正向查找
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
11 lastIndexOf()逆向查找
public int lastIndexOf(Object o) {
return lastIndexOfRange(o, 0, size);
}
12 clone
public Object clone() {
try {
//调用父类的克隆方法,克隆空的ArrayList实例
ArrayList<?> v = (ArrayList<?>) super.clone();
//复制数组,然后赋值
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
13 Object[] toArray() 转化为数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
14 get(int index) 获取元素
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}
15 remove(int index) 删除指定位置元素
public E remove(int index) {
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);
return oldValue;
}