构造函数
/**
*elementData 是内部存放数据的数字,
*DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是用来标识无参构造函数空数组的一个final对象
*无参构造函数中,将DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的引用赋值给了elementData
**/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
*EMPTY_ELEMENTDATA 是用来标识有参构造函,且入参为空数空数组的一个final对象。
*EMPTY_ELEMENTDATA 与DEFAULTCAPACITY_EMPTY_ELEMENTDATA的区别在于后续会根据他们来判断膨胀的速度
*有参构造函数中,将EMPTY_ELEMENTDATA 的引用赋值给了elementData
**/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
*如果initialCapacity > 0,那么elementData等于一个Object数组,长度为入参;否则等于EMPTY_ELEMENTDATA
**/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
*elementData 等于入参toArrayList,size等于入参长度,elementData 等于EMPTY_ELEMENTDATA
**/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
添加操作
/**
*修改次数加一
**/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
/**
*如果elementData的长度等于size,说明数组满额了,那么执行扩容。elementData[s] = 要插入的元素,size加一
**/
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
/**
*以size+1为最小容量的扩容(要放下这个元素嘛)
**/
private Object[] grow() {
return grow(size + 1);
}
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}
/**
*newCapacity等于原容量+原容量整除2,差不多1.5倍
*因为是位运算,原容量等于0的时候,新容量也是0。
*如果elementData 等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,也就是无参构造函数构建的,那么取DEFAULT_CAPACITY,
*minCapacity的最大值,在add(E)中,是取 10和1的最大值。
*还有一种情况:入参为int的那个构造函数,传入0,直接返回minCapacity,在在add(E)中,是1。
*如果新容量小于MAX_ARRAY_SIZE,那么返回计算出的新容量,否则返回Integer.Max(其实就差8)
**/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE)
? Integer.MAX_VALUE
: MAX_ARRAY_SIZE;
}
读取操作
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
E elementData(int index) {
return (E) elementData[index];
}
很简单,检查一下是否越界,然后从数组中取到这个值并返回
删除操作
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+1以及之后的数据,复制到index到之后的位置。将多出来的尾元素置为null,然后size–