ArrayList提供了四个方法添加元素,前两种添加一个元素,后两种为添加一Collection。
第一种我们前面已经见过并且分析过。我们看一下下面的图解以及代码
public boolean add(E e) {
//确保数组长度,不够则扩展
ensureCapacityInternal(size + 1);
//添加元素
elementData[size++] = e;
return true;
}
第二种是在指定的位置添加一个元素。System.arraycopy(elementData, index, elementData, index + 1,
size - index);这方法很重要,list元素的添加很大程度上都依赖这个方法。第一个参数为要复制的源数组,第二个参数为要复制的开始位置,第三个是要复制的目的数组,第四个参数是复制到目的数组的开始位置,第五个参数为要复制的长度。
public void add(int index, E element) {
//检查插入索引位置,超出范围,抛出异常,跟List长度作比较
rangeCheckForAdd(index);
//根据情况扩展数组长度,如果扩展数组长度,进行一次数组的复制
ensureCapacityInternal(size + 1);
//赋值新数组
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//添加元素
elementData[index] = element;
//list长度加1
size++;
}
private void rangeCheckForAdd(int index) {
//如果索引大于List长度或者小于0,抛出异常
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
第三个方法是添加一个集合
public boolean addAll(Collection<? extends E> c) {
//转换为数组
Object[] a = c.toArray();
int numNew = a.length;
//确保数组长度足够存储
ensureCapacityInternal(size + numNew);
//直接将转换后的数组从索引0开始复制
//复制到elementData,从size开始复制
//复制长度为a的长度,即集合长度
System.arraycopy(a, 0, elementData, size, numNew);
//list长度增加
size += numNew;
//如果要添加的集合长度为0,添加失败,即没添加
return numNew != 0;
}
第四个方法是在指定的位置添加一个集合,在指定的位置添加一个集合,则至少要对数组进行两次的复制,第一次移动元素,一遍有足够的空间添加集合,第二次才是添加集合,并且都是用System.arrayCopy()进行数组的处理。
public boolean addAll(int index, Collection<? extends E> c) {
//也要检查索引是否越界
rangeCheckForAdd(index);
//转换为数组
Object[] a = c.toArray();
int numNew = a.length;
//确保数组长度足够
ensureCapacityInternal(size + numNew);
//要移动的元素个数
int numMoved = size - index;
if (numMoved > 0)
//移动元素
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//添加集合
System.arraycopy(a, 0, elementData, index, numNew);
//长度增加
size += numNew;
return numNew != 0;
}
后续我们自己实现一个自己的List。