ArrayLIst在指定位置插入的内部实现


今天看到一个问题:ArrayList的add方法有两种,add到指定位置是怎么实现的?

发现自己对这块地方不熟悉,所以立马去看了ArrayList下的源码

// 第一个
public boolean add(E var1) {
        this.ensureCapacityInternal(this.size + 1);
        this.elementData[this.size++] = var1;
        return true;
}

// 第二个
public void add(int var1, E var2) {
    // 判断插入位置是否在[0,size)内
    this.rangeCheckForAdd(var1);
    // 检查数组容量大小,不够则进行扩容(扩容因子为1.5)
    this.ensureCapacityInternal(this.size + 1);
    // native修饰方法,在JVM由c语言执行
    System.arraycopy(this.elementData, var1, this.elementData, var1 + 1, this.size - var1);
    // 在指定位置插入元素
    this.elementData[var1] = var2;
    // 记录数组元素个数
    ++this.size;
}

第一个add方法没什么好说的,如果你对ArrayList有一定了解的话,它底层是使用一个动态数组实现的,其中ensureCapacityInternal是检查数组容量大小,如果容量大小不够还会进行扩容操作,再将元素添加至末尾,并记录数组元素个数。

第二个add方法主要分为五步:

  • rangeCheckForAdd该方法判断插入位置是否在[0,size]内(size指数组元素个数)
  • ensureCapacityInternal检查数组容量大小,不够扩容
  • System.arraycopySystem类下的方法,查看源码:
public static native void arraycopy(Object var0, int var1, Object var2, int var3, int var4);

可知arraycopy使用native关键字修饰,表示该方法是在在JVM由c语言执行的,它的作用通过查询jdk文档可知:

// 在ArrayList应用该方法实现效果

// elementData = [1,2,4,5,6,0,0,0,0,0]
// 参数列表(elementData, 2, elementData, 3, 3)
System.arraycopy(this.elementData, var1, this.elementData, var1 + 1, this.size - var1);
// elementData = [1,2,4,4,5,6,0,0,0,0]
  • 再在修改后的数组指定位置添加元素
  • 记录数组元素个数(++size)