1.add()
public boolean add(E e) {
//1.判断是否需要扩容
//2.进行扩容
//size+1:因为添加了一个元素所以要加1
ensureCapacityInternal(size + 1); // Increments modCount!!
//对扩容完的data进行添加数据
//size++:因为添加了一个元素所以要加1
elementData[size++] = e;
//前面没有问题表示添加成功返回true
return true;
}
/**
* 扩容方法
* @param minCapacity 最小扩容大小
*/
private void ensureCapacityInternal(int minCapacity) {
//1.对比判断最小扩容大小,默认最小10
//2.进行扩容
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 扩容判断
* @param elementData 数据
* @param minCapacity 最小扩容大小
* @return 最小扩容大小
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果当前的数据为空DEFAULTCAPACITY_EMPTY_ELEMENTDATA={},则最小扩容大小和默认最小10容量比较找出大的
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//返回最小扩容大小
return minCapacity;
}
/**
* 扩容判断
* @param minCapacity 最小扩容大小
*/
private void ensureExplicitCapacity(int minCapacity) {
//修改操作数加1
modCount++;
// 如果需要扩容的容量>数据的长度进行扩容,否则不需进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 最终扩容方法
* @param minCapacity 最小扩容大小
*/
private void grow(int minCapacity) {
// 原来的容等于数据长度
int oldCapacity = elementData.length;
//新容量等于原来容量*3/2,也就是原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新容量<最小扩容大小则容量扩容为最小扩容大小也就是默认10或者size+1
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新容量>最大数组容量(Integer.MAX_VALUE-8)
if (newCapacity - MAX_ARRAY_SIZE > 0)
//最大容量判断
newCapacity = hugeCapacity(minCapacity);
//扩容完之后进行数据拷贝,把原来的数据拷贝到扩容后的数组里
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
* 扩容判断
* @param minCapacity 最小扩容大小
* @return 最大容量
*/
private static int hugeCapacity(int minCapacity) {
//如果容量已经超过int的最大限度,抛出异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果最小扩容大小>数组最大容量(Integer.MAX_VALUE-8)返回Integer.MAX否则等于Integer.MAX_VALUE-8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
总结:在添加数据的时候,需先进行扩容判断,如果容量不够则进行扩容。容量扩容成原来数据长度的1.5倍,初始化容量默认最小为10,最大容量为Integer.MAX_VALUE。
2.addAll()
public boolean addAll(Collection<? extends E> c) {
//转化成数组
Object[] a = c.toArray();
//获取数据长度
int numNew = a.length;
//原有的数据长度+添加的数据长度进行扩容
ensureCapacityInternal(size + numNew); // Increments modCount
//扩容完进行数据拷贝,拷贝到扩容后的数组里
System.arraycopy(a, 0, elementData, size, numNew);
//现在数据长度=原有的数据长度+添加的数据长度
size += numNew;
//如果添加的数据长度不为0返回true,否则false
return numNew != 0;
}
3.get()
public E get(int index) {
//检查是否越界
rangeCheck(index);
//返回下标数据
return elementData(index);
}
private void rangeCheck(int index) {
//如果查找的下标大于数据长度,抛出异常
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
总结:获取的时候,需要检查下标是否越界,没有返回对应下标的数据。
4.remove()
public E remove(int index) {
//检查数组是否越界,越界抛出异常
rangeCheck(index);
//操作数++
modCount++;
//获取数据
E oldValue = elementData(index);
//拷贝数据的长度
int numMoved = size - index - 1;
//如果需要拷贝数据
if (numMoved > 0)
//1.目标数据elementData,2.要从哪个地方开始拷贝index+1,3.拷贝的长度numMoved,4.数据拷贝到这个对象(第3个elementData),5.目标数组的开始拷贝起始位置index
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//把最后的数据置空,并长度减1
elementData[--size] = null; // clear to let GC do its work
//返回删除的数据
return oldValue;
}
移除图解(图片来自小博哥)
总结:删除的时候,判断是否下标越界,先进行数据拷贝,然后把最后的数据置为空、长度减1。