• 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;
       }
  • 相关阅读:
    MapBox TileMill
    优秀电影
    Mapnik 编译安装过程
    Debian 入门安装与配置2
    学习opengl十大网站(转载)
    PostgresSQL 学习资料记录处
    c++模板编程-异质链表
    Linux-统一事件源
    三组I/O复用模型的比较
    ZigZag-LeetCode
  • 原文地址:https://www.cnblogs.com/zhexuejun/p/11165188.html
Copyright © 2020-2023  润新知