ArrayList-添加,删除原理-源码扩容grow(int minCapacity)


赠人玫瑰,手有余香,你的点赞,我的动力
更多分享可见:
在这里插入图片描述

总结

所谓动态数组的扩容,就是包装下面这个api 。
Arrays.copyOf(elementData, newCapacity);
没有耐心的小伙伴直接跳转到 grow(minCapacity) 目录处

1预备知识

运用:
1 Arrays.copyOf(elementData, newCapacity); //扩容数组的api
2 System.arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length); //复制数组的api

  • 1
import java.util.Arrays;

public class ArrayDemo {
	public static void main(String[] args) {
    	int[] arr1 = {1, 2, 3, 4, 5}; 
    	int[] arr2 = Arrays.copyOf(arr1, 5);
    	int[] arr3 = Arrays.copyOf(arr1, 10);
    	for(int i = 0; i < arr2.length; i++) 
        	System.out.print("arr2:"+arr2[i] + " "); 
    		System.out.println();
    	for(int i = 0; i < arr3.length; i++) 
        	System.out.print("arr3:"+arr3[i] + " ");
	}
} 

运行结果:
arr2:1 2 3 4 5
arr3:1 2 3 4 5 0 0 0 0 0

可见扩容后的数组 补充了几个零,如果数组是对象,应该是补充几个null

  • 2
    System.arraycopy(Object src, int srcPos,
    Object dest, int destPos,
    int length);

参数说明:
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:目标数据中的起始位置
length:要拷贝的数组元素的数量

简单说:
我要复制一个名字为src 的数组,
从src 数组下标为srcPos 的位置开始复制,
复制的个数是 length ,
复制的内容写到哪里 dest 数组中!
从dest 数组的的destPos 下标位置开始复制!

2源码分析

源码:add(E e) 原理实现

add(E e):添加一个元素到列表的末尾。

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 确保数组大小够不是否,需要扩容不。
        /*1 elementData 是Arraylist中存放元素的真正数组,size是当前数组中存了几个元素,而不是数组的长度!!!
        *2 把添加的元素放入数组中已存入元素个数的+1位置!
        */
         elementData[size++] = e;
        return true;
    }

记住size+1 代表加入一个元素后当前总元素的数量 很重要!!!!

  • 下一步
    ensureCapacityInternal(size + 1); 如何扩容
    private void ensureCapacityInternal(int minCapacity) {
    //如果new ArrayList() 这样的实例对象,则ArrayList大小就是DEFAULT_CAPACITY--> 10大小
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
	//确定是否需要扩容,下一步进入
        ensureExplicitCapacity(minCapacity);
    }
  • 下一步
    要注意:当前的minCapacity 除了无惨构造实例化设置10 ,其他情况就是等于 size+1 ,代表当前list列表中的需要存储的总元素个数
    ensureExplicitCapacity(minCapacity);
   private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // 如果小存储的的总元素个数大于当前数组的长度,则扩容执行grow(minCapacity)
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

源码:grow(minCapacity) ArrayList核心

  • 下一步 grow
    grow(minCapacity)
 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
             //表示扩容一半,>>1 代表右移一位,在数学上就等同于除2,所以本身长度 oldCapactiy+自身一半,  这是扩容后的长度。
        int newCapacity = oldCapacity + (oldCapacity >> 1); 
        //扩容前有两个情况需要注意下:
       //情况1 如果扩容后的长度还是小于当前需要存入的个数minCapacity ,为扩容的大小
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
       //情况2 如果扩容后的长度,大于ArrayList 类中规定的最大长度,处理情况,暂时不看
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //程序走到这里就代表老老实实的扩容了,怎么样看到Arrays.copyOf()  很熟悉了吧
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

  • 下一步
    我们在继续分析Arrays.copyOf(elementData, newCapacity);
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());//点击下一步
    }

  • 下一步
   public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
   		/*下边三元表达式,代码看起来很恶心,表达的意思是:要被复制的目标是不是Object[]  类型的
   		*如果是重新建一个Object[newLength]  数组,记着newLength 传递的是我们需要扩容数组的大小!!
   		*如果不是则把目标包装成一个数组,大小也是newLength
   		*最终目的就是保证传入给System.arraycopy() 方法中参数"copy" 的值是一个我们扩容后的新数组
   		*/
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
       //眼熟吧!!!上面例子中有解释     
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

源码:remove(int index)删除实现

如果删除23 这个数字,要把位置在7,8,9上的元素移动到6,7,8的位置上!
在这里插入图片描述

所以源码分析

    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);
		//复制的个数
        int numMoved = size - index - 1;//删除23,则后面的元素的位置index 7 8 9,所以需要3个
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);//numMoved代表需要复制几个!
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

更多记录请看:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值