通过阅读ArrayList源码分析ArrayList的扩容机制

这里阅读的是JDK8的源码,使用无参构造函数的话是创建一个空数组,第一次调用add方法是才生成一个大小为10的数组。

  • 执行add方法,会先调用ensureCapacityInternal(size+1)方法,执行完毕后elemData[size++]=e,返回布尔类型。
    image.png

  • ensureCapacityInternal()方法内部是一个嵌套方法,外层是调用ensureEplicitCapacity(),它的参数为calculateCapacity(),calculateCapacity的作用是检测此时数组是否为空(即是否是首次添加数据),返回10(定义的默认容量)与参数的最大值给外层ensureEplicitCapacity()方法.
    image.png
    image.png

  • ensureEplicitCapacity()方法中有一个if判断minCapacity是否大于现在的数组长度,是则扩容,执行grow()方法。
    image.png

  • grow先根据旧的数组长度生成newCapacity=oldCapacity + (oldCapacity>>1),及扩大1.5倍。实际上是偶数扩大1.5倍,奇数因为会丢失小数略小于1.5倍。然后进行两次if判断,第一个if会判断此时新容量是否足够了,若不够 newCapacity=minCapacity。第二个if判断此时newCapacity是否比最大数组长度(ArrayList中定义的常量MAX_ARRAY_SIZE,它等于整数最大值减8)还要大,如果判断为true,则newCapacity等于hugeCapacity的返回值。前面的语句都顺利执行完毕后,调用Arrays.copy方法生成新扩容后的数组
    image.png

  • hugeCapacity方法先判断是否minCapacity小于0,如果是那么抛出oom异常, 否则如果minCapacity比MAX_ARRAY_SIZE小返回MAX_ARRAY_SIZE,否则返回Integer.MAX_VALUE。
    image.png

ensureCapacity()方法。

我们可以在ArrayList类中看到这样一个方法,它并没有被ArrayList自身的其他方法调用过,显示是留给用户(程序员)调用的。
image.png
可以在进行多次add方法前先用此方法扩容,一步到位,避免之后频繁触发扩容,影响效率

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值