ArrayList的动态扩容的实现

   ArrayList可以实现容量的自适应的增加,通过阅读源代码,对这个机制进行一下简单的分析。

首先,ArrayList有一个初始的默认大小,为10.

 private static final int DEFAULT_CAPACITY = 10;


从add方法为入口

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


可见,在添加元素之前,会先调用ensureCapacityInternal这个方法,那就再进到这个这个方法中去。

 private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

       首先,看看数组是否为空,如果是,就将DEFAULT_CAPACITY和minCapacity的较大的一个作为初始大小赋值给minCapacity DEFAULT_CAPACITY是10,minCapacity就是add方法中传入的size + 1。


        如果数组不为空,就直接执行ensureExplicitCapacity方法。ensureExplicitCapacity方法的实现如下:

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

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

     在这个方法里,会比较minCapacity 与elementData.length 的大小。当第一次插入值时,由于minCapacity 一定大于等于10,而

elementData.length是0,所以会去继续执行grow方法,那就继续进入到这个方法中去。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);
    }

   这个方法首先计算出一个容量,大小为oldCapacity + (oldCapacity >> 1)。即elementData数组长度的1.5倍。再从minCapacity 和

这个容量中取较大的值作为扩容后的新的数组的大小。


    这时,会出现两种情况:

一. 新的容量小于数组的最大值MAX_ARRAY_SIZE ,即

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

     最大的容量之所以设为Integer.MAX_VALUE - 8,在定义上方的注释中已经说了,大概是一些JVM实现时,会在数组的前面放一些额外的数据,再加上数组中的数据大小,有可能超过一次能申请的整块内存的大小上限,出现OutOfMemoryError。



二. 新的容量大于数组的最大值MAX_ARRAY_SIZE 

这时,又会进入另一个方法hugeCapacity

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

会对minCapacity 和 MAX_ARRAY_SIZE进行比较,minCapacity 大的话,就将Integer.MAX_VALUE 作为新数组的大小,否则将MAX_ARRAY_SIZE作为数组的大小。


      最后,就把原来数组的数据复制到新的数组中。调用了Arrays的copyOf方法。内部是System的arraycopy方法,由于是native方法,所以效率较高。


通过分析可以发现,ArrayList的扩容会产生一个新的数组,将原来数组的值复制到新的数组中。会消耗一定的资源。所以我们初始化ArrayList时,最好可以估算一个初始的大小。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值