今天稍微看了下jdk 源码中 ArrayList 的两个常用操作add 和 remove 以下是个人学习心得,个人学习记录,如有错误,欢迎大家纠正。
ArrayList 实际上就是构建一个可变长度大小数组对象,每个ArrayList 对象维护一个对象数组,初始化空构造器默认初始化大小为10的对象数组,当然,也可以自定义长度。
先是add操作。上源码。
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
容易发现首先调用了一个方法ensureCapacityInternal(size +1 ),顾名思义就是增加了一个元素之后,确保对象数组长度是否足够大。接下来,
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
先是一个判断当前对象数组是否为空数组,若是则把默认大小和当前预计大小做一个大小比较,挑出较大的作为扩展后数组的长度。然后,
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
判断当前初始化的数组长度是否大于目标预计的大小,如果是,则不需要扩展,如果不是则调用grow操作执行实际扩展。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
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);
}
可见,在老容量前提上得到一个预计新容量newCapacity,看看newCapacity是否足够大过请求的目标容量minCapacity,如果不是,则将较大的赋值给newCapacity,最后调用Arrays的方法构建一个newCapacity大小的数组。
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);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
还是首先判断index是否超出边界,然后numMoved是指被移除的元素后面还有元素的个数,然后将index+1往后的元素在同一个数组内均前移一位,达到最后目的。