[Java集合源码阅读]-ArrayList扩容机制

ArrayList扩容机制主要通过下面代码实现,代码对扩容时是否会溢出进行了处理。

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

扩容流程:

首先扩容1.5倍,如果1.5倍后还是不能满足最小要求则将当前最小要求数量minCapacity作为新的扩容大小newCapacity,判断newCapacity与MAX_ARRAY_SIZE值大写,如果newCapacity比MAX_ARRAY_SIZE大则调用hugeCapacity方法。

其中hugeCapacity方法中有个minCapacity判断,很多人不理解这个判断是为什么?要理解这个就需要理解下二进制一些知识了,Int的最大值是2^32-1,设想如果当前数组的最大值为2^32-1,list中还想网里面添加数据,minCapacity将会变成2^32-1加1,在int中结果是个负数,这样将会抛弃内存溢出错误。

分两种情况考虑:

1.minCapacity<0

这种情况说明当前数组最大数量已经是Integer.MAX_VALUE了,即2^32-1。这样int newCapacity = oldCapacity + (oldCapacity >> 1)将得到一个负数为-1073741826,显然newCapacity>-2^32,

若minCapacity>=-1073741826,(newCapacity - minCapacity)小于等于于0,若minCapacity<-1073741826,(newCapacity - minCapacity)大于0,

情况a:

若minCapacity>-1073741826,(newCapacity - minCapacity)小于0,此时newCapacity=minCapacity<-1073741826,这里有分两种情况

若minCapacity<-9且minCapacity>-1073741826时直接调用hugeCapacity抛出异常,

若0>minCapacity>=-9,此时将会扩容一个负数,最终直接抛出了NPE。

情况b:

如果minCapacity==-1073741826,会有newCapacity-MAX_ARRAY_SIZE>0,直接调用hugeCapacity并在方法内部抛出异常。

情况c:

如果minCapacity<-1073741826,newCapacity - minCapacity大于0,此时newCapacity=1073741826,跟情况b一样。

 

minCapacity>0同理。

 

转载于:https://my.oschina.net/wenbo123/blog/1614221

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值