ArrayList的add方法实现

        ArrayList的底层是由数组实现,所以所有的操作都是围绕数组展开,要想理解add方法,就得先了解数组的增加,所以我们先实现一个数组的add,数组的添加可以从尾部增加或者其他位置插入,

如果在数组的尾部插入,只需要拿到数组的长度,直接在该索引处赋予元素值,下面自己手动简单实现一个在数组任意位置实现数组元素添加:

public class MyArray {
   public static void main(String[] args) {
         /*创建一个数组*/
         Object[] objectArray = new Object[10];
         for (int i = 0; i < 10; i++) {
             objectArray[i] = i;
         }
         System.out.println("原数组");
         for (int i = 0; i < objectArray.length; i++) {
            System.out.print(objectArray[i] + ",");
         }
         System.out.println();
         System.out.println("插入后的数组");
         Object[] newArray;
         try {
            newArray = MyArray.add(objectArray, 3, "hello");
            for (int i = 0; i < newArray.length; i++) {
                System.out.print(newArray[i] + ",");
            }
         } catch (Exception e) {
            e.printStackTrace();
         }
   }
   /*在一个数组的任意位置插入一个元素*/
   public static Object[] add(Object[] objectArray, int index, Object object) throws Exception {
       if(index < 0 || index - objectArray.length > 0) {
           throw new Exception("数组索引无效" + index);
       }
       Object[] newObjectArray = new Object[objectArray.length];
       /*首先将插入位置之前的所有元素拷贝到一个新的数组中*/
       for (int i = 0; i < index; i++) {
           newObjectArray[i] = objectArray[i];
       }
       /*然后将剩下的元素拷贝到插入位置加1后面的位置*/
       for (int i = index + 1; i < objectArray.length; i++) {
           if(!"".equals(objectArray[i])) {
              newObjectArray[i] = objectArray[i - 1];
           }
       }
       /*将新增的元素放到插入的位置*/
       newObjectArray[index] = object;
       return newObjectArray;
   }
}

(1) add方法

      如果想在数组的任意位置插入元素,我们需要建立一个新的数组,将插入位置前面的元素拷贝到新数组中,将插入位置后面的元素的下标都后移一位,将插入位置腾出,

将需要插入的元素放入该位置,比起上面的demo,ArrayList的实现稍微复杂,在上述的过程中加入了扩容机制,也不会上面一样将一个数组整个复制到另一个新数组中,

而是原来数组插入位置后面的元素按顺序复制到原数组插入位置+1的位置,下面为ArrayList的add方法源码:

    public void add(int index, E element) {
        /*判断插入的索引是否符合ArrayList范围,在0 和 size之间,size是ArrayList实际元素个数,不包括底层数组的null元素*/
        rangeCheckForAdd(index);
        /*扩容机制:判断添加是否需要进行扩容*/
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        /*将旧数组拷贝到一个新数组中,参数:被复制的原数组, 被复制数组的第几个元素开始复制, 复制的目标数组, 从目标数组index + 1位置开始粘贴, 复制的元素个数,*/
        System.arraycopy(elementData, index, elementData, index + 1, size - index);           
        /*将新元素赋予该下标*/
        elementData[index] = element;
        /*元素个数+1*/
        size++;
    }

(2) addAll()方法

       ArrayList的addAll()方法的实现和add()方法实现思路一致,只不过需要移动的元素更多,由于数组结构的特性,导致这样的操作对于数据大的ArrayList的插入操作,

会严重影响代码执行的效率,所以开发中我们应该尽量避免出现对数据元素多的ArrayList频繁add。

 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);
            /*数组长度+numNew*/
            size += numNew;
            return numNew != 0;
        }
   public boolean addAll(int index, Collection<? extends E> c) {
       /*判断索引是否有效*/
       rangeCheckForAdd(index);
       Object[] a = c.toArray();
       int numNew = a.length;
       /*扩容机制:判断是否需要扩容*/
       ensureCapacityInternal(size + numNew);  // Increments modCount
       /*需要移动的元素个数*/
       int numMoved = size - index;
       /*如果插入位置不在尾部,则移动原数组index以后的元素,未插入c腾出空间,如果在尾部,与addAll(Collection<? extends E> c)方法相同*/
       if (numMoved > 0)
           System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
       /*将需要插入的数组插入到腾出空间中*/
       System.arraycopy(a, 0, elementData, index, numNew);
       /*长度+numNew*/
       size += numNew;
       return numNew != 0;
   }
原文地址:https://www.cnblogs.com/zhexuejun/p/11165188.html