ArrayList源码解析
new
- new ArrayList()
public ArrayList() {
//此时为空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//初始化为长度为initialCapacity的Object数组。
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
下面都按new ArrayList()分析代码
add
- add(E e)
public boolean add(E e) {
/**
*size是类的私有变量,也就是默认为0;
*ensureCapacityInternal方法用于对elementData扩容
*/
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;//通过下标对数组赋值
return true;
}
- ensureCapacityInternal()
private void ensureCapacityInternal(int minCapacity) {
/**
* 第一次add数据时elementData为{}
*/
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//DEFAULT_CAPACITY=10,默认扩充为10个长度的数组
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
/**
* 扩容
*/
ensureExplicitCapacity(minCapacity);
}
- ensureExplicitCapacity()
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
/**
* 如果需要扩容的长度>数组容量,则扩容。
* elementData.length:数组容量
* size:elementData中存放的数据个数
*/
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//扩容的具体代码
grow(minCapacity);
}
- grow()
private void grow(int minCapacity) {
// overflow-conscious code
//原数据容量,第一扩容时oldCapacity=0
int oldCapacity = elementData.length;
//新容量为原容量+原容量的一半(1.5*oldCapacity)。
int newCapacity = oldCapacity + (oldCapacity >> 1);
//newCapacity可能为负值
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
/**
* MAX_ARRAY_SIZE=Integer.Integer.MAX_VALUE - 8
* 如果新容量大于MAX_ARRAY_SIZE,将数组扩展到最大长度。
*/
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//复制数据,最耗性能的地方
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;
}
由这段代码可知,当size=MAX_ARRAY_SIZE/Integer.MAX_VALUE,再增加数据就越界了。
remove
public E remove(int index) {
rangeCheck(index);
modCount++;
//获取原始值
E oldValue = elementData(index);
//要移动的数据量,删除数据后会将后面的数据前移一位
int numMoved = size - index - 1;
if (numMoved > 0)
//移动数据
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
/**
*将原来最后一位数据设置为null,确保可以GC可以回收数据
*(只有在最后一位的数据被删除后,GC发生时才有可能回收最后一位指向的对象)。
*/
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
还有public boolean remove(Object o)方法,和上面的remove基本相同,只是不返回原值。
总结
扩容会开辟新空间,并copy原值到新空间中;删除涉及到数据的移动;这两者都比较耗性能,最好是声明恰当的数据长度。如果程序中不能用下标定位数据,或删除较频繁时,可以考虑使用LinkedList。