ArrayList的扩容原理(详细带代码讲解)
ArrayList的扩容原理(详细带代码讲解)
ArrayList是Java中最常用的集合之一,其扩容机制直接影响着程序的性能。本文将通过源码分析,详细讲解ArrayList的扩容原理,帮助读者深入理解这一重要数据结构的内部实现。
ArrayList的源码
ArrayList的底层是Object类型的数组,下面我们先来看一下ArrayLIst的源码:
这里调用ArrayList的无参构造方法,将这个被final修饰的名为“DEFAULTCAPACITY_EMPTY_ELEMENTDATA”的空数组赋值给底层创建的名为elementDate的数组。可见现在elementDate当前为空。
第一次添加元素时
第一次添加元素时,调用了ensureCapacityInternal方法,里面是size+1,由下图可知size是默认值0,所以ensureCapacityInternal方法参数为1,接下来进入此方法。
我们可以得知minCapacity的值为1,先调用calculateCapacity方法传入的值分别为elelmentData和minCapacity,由上文可知它们的值分别为0和1。
进入calculateCapacity方法:我们已知elementData与 DEFAULTCAPACITY_EMPTY_ELEMENTDATA的值都为0,所以if条件判断语句成立,返回的是DEFAULT_CAPACITY和minCapacity中间的最大值。下图系统给出DEFAULT_CAPACITY的值为10,所以我们返回的值为10。
接下来进入ensureExplicitCapacity方法modCount的默认值为0,进行++操作之后值为1;if条件判断minCapacity为1,elementData.lenght为0,进入grow方法。
参数为minCapacity 0,将数组长度赋值给oldCapacity所以旧容量的值为0,新容量的值是旧容量加上旧容量右移一位的值,也就是旧容量的1.5倍。所以新容量是0,接下来条件判断,满足第一个if条件 新容量被1赋值,第二个if判断不满足,则进入复制数组环节,elementData长度为1并将元素传进去调用copyOf方法。
返回值是一个泛型类型的数组,长度为新容量的长度,得到一个数组接下来依次返回原调用处。
当数组添加元素长度超过10之后,在grow方法处正常情况下有两种扩容方法:
第一种:新容量等于旧容量的1.5倍,如果足够用则继续接下来的复制。
第二中:也就是当扩容到1.5倍还是不够用的时候,则会直接扩容到需要的大小。
简单来说,在正常情况下ArrayList的扩容机制为:
- 创建ArrayList对象:内部数组elementDate被初始化成一个空数组;
- 当往集合中添加第一个元素时,数组初始化容量为10;
- 已经添加了10个元素,容量不足,扩容为原数组的1.5倍;