ArrayList扩容
查看的ArrayList源码是JDK1.8版本
首先,对于ArrayList扩容,当调用无参构造new一个ArrayList时,此时size=0,数组为空。如果指定了数组大小的构造函数,或者是指定了collection元素的列表,这两个构造函数,初始值size就是自定义的了。
然后当执行add方法时,一定会先执行ensureCapacityInternal方法,参数叫做minCapacity(最小容量)=size+1。
而ensureCapacityInternal()函数里,还会计算一次最小容量,主要是给空参创建的加个默认容量,如果已经有容量了,不会进行更改。
之后就进入到了扩容的核心函数,grow(int minCapacity)。
可以看到newCapacity=oldCapacity+(oldCapacity >> 1);也就是旧容量的1.5倍。奇数的话最后一位的1会被消去。但是,新容量大小还要经历两次判断,最后才会执行copyOf函数。
一是如果新容量小于最小所需容量,可以知道,这种情况旧容量太大导致数值溢出,newCapacity数值溢出,小于minCapacity了。
二是判断新容量是不是大于最大数组长度(默认是Integer.MAX_VALUE-8),如果大于,就进到了这个函数
hugeCapacity的逻辑主要是判断最小所需容量是不是已经<0了,会报OOM异常,大概是minCapacity=size+1.size=Integer.MAX_VALUE才会出现这种情况。
然后判断minCapacity是不是大于最大数组长度,如果是,新容量=Interger.MAX_VALUE(如果再次扩容,就会跑到上面的判断逻辑了,再次扩容 size+1会成负数了)。
如果还没有大于最大数组长度,就会新容量=最大数组长度。
到此,新容量的计算就完成了,最后执行复制数组方法。扩容完成。