一、原理
- 利用空参创建的集合,在底层创建一个默认长度为0的数组名字为elementData,且还有一个底层变量size,用来记录元素的个数。
- 添加第一个元素时,底层会创建一个新的长度为10的数组,默认初始化值为空。所以我们一般会认为ArrayList的底层的数组默认长度是10。
- 底层的size这个变量有两层含义,第一层含义表示的是现在元素的个数,也就是集合的长度,第二个表示下次存入位置,每次存入数据时size都会加加。
- 当集合原始数组存满,并且还要继续添加时,数组会自动扩容1.5倍,此时size为15。如果又满了还会继续扩容为当前长度的1.5倍。
- 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
二、源码解析
添加一个元素数据
我们新创建一个ArrayList集合时,底层利用空参创建的集合,在底层创建一个默认长度为0的数组名字为elementData,在我们使用add方法添加第一个数据时,底层会再调用另一个add方法,底层的这个add方法有三个参数,1.当前要添加的元素,2.集合底层的数组名字3.集合的长度/当前元素应存入的位置,这个底层的add方法调用的时候会判断添加的位置是不是跟数组的长度相等,如果相等就会调用grow(无参的数组扩容的方法),然后无参的grow的方法再调用有参的grow方法把现有的个数+1传递过去,第一次添加时会进行一个比较。比较结束会把这个数组返回。
添加第十一个元素数据
add方法会调用grow方法(无参的数组扩容的方法),然后无参的grow的方法再调用有参的grow方法把现有的个数+1传递过去(此时的参数就表示添加完当前元素之后的最小容量),由minCapacity(最小的容量)这个参数接收,然后保存会先通过elementData.length保存老的容量。然后调用ArraySupport的newLength方法,这个方法有三个参数1.老容量2.理论上至少要新增的容量3.老容量右移一位(右移表示除以二)也就是新增容器大小.
执行newLength方法时会有两种情况:
第一种情况:如果一次添加一个元素,那么第二个参数-定是1,表示此时数组只要扩容1个单位就可以了。
第二种情况:如果一次添加多个元素,假设100.那么第二个参数是100,表示此时数组需要扩容100个单位才可以
因为会先做一个比较,它要看你至少要添加的容量跟默认添加的容量那个更大,然后进行返回。
最后grow方法会调用Arrays的copyOf的方法进行创建一个新的数组并进行拷贝