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 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 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。