ArrayList数组是怎么扩容,扩容的特点,能扩容到多少

问题:ArrayList数组是怎么扩容,扩容的特点,能扩容到多少

源码分析

  1. ArrayList默认容量为10,没有加载因子,一次最大扩容为16。
  2. 无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10。DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示的是空的数组对象。
  3. 有参构造:
    第一种:传int参数
    如果这个初始化参数大于0,那么就会设置对象大的数组存储区的容量大小与初始化参数相等。
    如果初始化参数等于0,那就返回EMPTY_ELEMENTDATA的空数组。
    第二种:传Collection
    首先,将Collection转化成数组,赋值给elementData,如果size不为0,那么就判断elementData是不是属于Object数组(这是为了避免出现在集合转数组时可能存在不返回Object数组的情况)。
    如果size为0,那就返回EMPTY_ELEMENTDATA的空数组。

小结:

  • EMPTY_ELEMENTDATA 表示的是我们在指定size为0的时候的空数组。
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示的一个默认的数组,一个空数组,没有特别指定它的size为0,它处于一个默认的、空的状态。

扩容机制:

  1. ArrayList扩容发生在add()方法调用的时候, 调用ensureCapacityInternal()来扩容的,通过方法calculateCapacity(elementData, minCapacity)获取需要扩容的长度。
  2. ensureExplicitCapacity方法可以判断是否需要扩容:
    2.1 首先进行判断是否大于默认容量10
    2.2 如果,小于默认容量10,直接在原来基础上+1,元素添加完毕
    2.3 如果,大于默认容量10,则需要进行扩容,扩容核心是 grow()方法
  3. ArrayList扩容的关键方法grow():
    获取到ArrayList中elementData数组的内存空间长度 扩容至原来的1.5倍
    3.1 扩容之前,首先创建一个新的数组,且旧数组被复制到新的数组中,这样就得到了一个全新的副本,我们在操作时就不会影响原来数组了。
    3.2 然后通过位运算符,将新的容量更新为旧容量的1.5倍。
    3.3 如果新的容量-minCapacity<=0,就拿新的容量-最大容量长度如果<=0的,那么最终容量=最大容量长度。
    3.4 如果新的容量-minCapacity>0,那么最终容量=新的容量。
  4. 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间。

从此方法中我们可以清晰的看出其实ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。

(例如:添加的容量为15,则minCapacity=15,15-16<=0,那么最终容量就是16。)

(例如:添加的容量为11,则minCapacity=11,15-11>0,那么最终容量就是15。)

特点:

  • ArrayList有自动扩容机制,它至少会保障这个数组的最小容量和你的数组大小一致,但是ArrayList的扩容机制并不是完全确定的,而且每次添加一个元素会消耗特定不变的缓冲时间。
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值