java技术栈直通之路系列 1.3 java集合基础 ArrayList扩容机制

ArrayList继承了AbstractList,实现了List接口,底层实现基于数组,因此可以认为是一个可变长度的数组。在这里插入图片描述
1.ArrayList中的变量
在讲扩容机制之前,我们需要了解一下ArrayList中最主要的几个变量:

  //定义一个空数组以供使用
        private static final Object[] EMPTY_ELEMENTDATA = {};
        //也是一个空数组,跟上边的空数组不同之处在于,这个是在默认构造器时返回的,扩容时需要用到这个作判断,后面会讲到
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        //存放数组中的元素,注意此变量是transient修饰的,不参与序列化
        transient Object[] elementData;
        //数组的长度,此参数是数组中实际的参数,区别于elementData.length,后边会说到
        private int size;

2.扩容机制
ArrayList有三个构造函数,不同的构造函数会影响后边的扩容机制判断,
2.1默认无参构造

public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

先看下面这段代码:
   List list=new ArrayList<>();
        for (int i=1;i<=15;i++){
            list.add(i);
        }

当第一次执行list.add()时会进入到下面这段代码中:

  public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

会先执行add方法中的ensureCapacityInternal方法,我们再次进入该方法,发现有如下四个方法均被使用:

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//修改次数

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//第二次扩容
        if (newCapacity - minCapacity < 0)//第一次扩容
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//一般执行不到这
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

DEFAULT_CAPACITY的值为10,calculateCapacity()主要用于第一次扩容,初始时elementData的大小为0,执行calculateCapacity()之后返回的当前 minCapacity大小为10,此时执行ensureExplicitCapacity()这个方法。

  private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//修改次数

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

当前minCapacity值为10,elementData.length的值为0,满足if (minCapacity - elementData.length > 0),执行grow方法,

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)//第一次扩容
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//一般执行不到这
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

由于newCapacity值为0,minCapacity为10,所以扩容为10,现在elementData[]这个数组内为10个null值。之后执行add的·剩余部分:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

执行过后,elementData[]的内容为第0个元素为1,其余九个为null.当执行add()第10(以0开始)个元素时,又要开始扩容了,我们发现grow方法中会执行这条语句: int newCapacity = oldCapacity + (oldCapacity >> 1);
于是再次扩容时就变为10+10/2=15个了。
2.2,有整数参数的构造函数

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

他会先把elementData[]值为申请的空间大小,然后当扩容时就和无参构造中讲的流程一样。同理,第三种构造方式也一样。

欢迎关注,后续会更新更多知识呦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值