1.jdk1.8与jdk11add()方法的源码不太相同;

首先分析jdk1.8处的源码:

alt

add()方法的整个流程分析:

alt

1.Add方***调用ensureCapacityInternel(mincapicity)是正的扩容,方法内会有一个参数用于并发修改的。 alt

2.ensureCapacityInternal() alt

3.cacluateCapacity(),用于确定所需要的最小容量; alt

4.ensureExplicitCapacity()函数,modCount++用于并发修改;次函数会调用grow方法用于数组的扩容 alt

5.grow()方法:这个方法中首先会获取就数组的容量,使用旧的数组的容量计算新的容量(大约是就数组的1.5倍),接着进行了边界值的判断,首先由于使用了位移的操作,所以当旧的容量为1时,右移两位后新的容量为1,明显小于了最小容量2,所以这时候采用了判断修改新的容量为最小容量;

第二种,当扩容时出现了溢出的情形,我们定义了max_array_size(他的值为Integer.Max - 8),以及使用了源码中常见的overflow_consicious code方式编码:方法中的写法的好处是,如果新容量溢出,那么由于max-array_size比较大,所以两者相减就能使得结果不溢出,那么就是成立的。如果是用大于号的话,那么就会是的负数大于正数,这显然是有问题的。一旦满足条件就会到方法中,执行hugecapacity(minicapicity),用于修改newcapicity的值,这个方法中会判断newcapicity,如果有这个值溢出则为负数那么就小于0,如果小于了0,就抛出异常,说明没有那么大的空间。否则就比较newcapicity和max _array_size的大小,如果前者大(大于max_array_size且未溢出),则返回inter.max,否则返回max_array_list()。

从这里的源码可以看出,ArrayList最多可以存Integer.Max()个元素;

alt

6.hugeCapacity():用于修改newcapicity的值,这个方法中会判断newcapicity,如果有这个值溢出则为负数那么就小于0,如果小于了0,就抛出异常,说明没有那么大的空间。否则就比较newcapicity和max _array_size的大小,如果前者大(大于max_array_size且未溢出),则返回inter.max,否则返回max_array_list()。

alt

7.Arrays.copyOf()方法:用于数组的扩容,元素的复制,以及将旧的引用指向新的数组;

alt

alt

因此,arraylist最大可以存储inter.max调用Arrays .copyof方法,复制数组。 这个方法需要两个参数一个是旧的数组,一个是新的数组的长度,这个方***创建一个数组并且把旧数组中内容赋值给新数组,并且返回新数组地址。接着修改旧的引用指向新的地址。