Java——ArrayList扩容机制

底部采用动态数组实现数据增加,删除。

size:ArrayList的实际存放数据个数,即我们常说的list长度,size()函数

elementDate:elementDate,ArrayList实际存放数据的数组,可动态扩容,我们所说的就是动态改变elementDate.length,从而达到扩容,实际的size一般都小于elementDate.length。可以通过trimToSize()函数将elementDate的容量改为数据实际的个数,去除多余的容量。删除元素并不会改变elementDate容量

transient Object[] elementData;

三种初始化方式:

//带初始容量的初始化 
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);
        }
    }


//无参初始化
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }


//collection作为参数
public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

采用无参初始化,elementData会是一个空数组,在添加第一个数据前,集合的容量为0,当添加第一个数据时,会进行扩容,将容量扩大为默认容量10。调用add()函数添加数据:

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

private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
}

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);
}

add()函数中size作为当前的elementData数组长度, ensureCapacityInternal(int minCapacity)函数,预计扩容为size+1,如果elementDate==DEFAULTCAPACITY_EMPTY_ELEMENTDATA,即为空数组,将容量扩展为相应的较大值,不为空扩展为size+1。即得到minCapacity(现在需要的的最小容量)

将上面得到的容量值作为参数传给ensureExplicitCapacity(int minCapacity)函数,将现在所需要的最小容量与elementData的长度作比较,进行扩容判断。若容量不足,则调用grow()函数扩容

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    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);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

获取elementDate的现有长度,将新的容量扩大为之前的1.5倍,与传入的最小需要的容量比较,获取合适值,再与MAX_ARRAY_SIZE比较,是否应该获取更大的空间,如果大于MAX_ARRAY_SIZE会获取更大的空间。最后Arrays.copyOf(elementData, newCapacity)进行加大容量。

添加第1-10个元素时,容量默认10,够用不会动态增加容量,当加入第11个时,开始动态扩容,原来的1.5被,即15。

Arrays.copyOf采用System.arraycopy进行数组扩容。

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值