通过第三讲的代码改进深入理解ArrayList(三),现在我们的代码能够实现底层数组的自动扩容,能够适应任意数量的元素插入,而且能够添加各种类型的元素,基本已经能够满足日常的开发需求。还有什么地方可以改进的呢?
首先来回顾一下上一讲的思路,在上一讲最突出的贡献就是在添加元素之前,进行了数组容量的判断,如果当前数组容量足够则直接添加,否则申请新的数组,将原数组的内容全部复制到新数组,然后再进行元素添加。
其核心的扩容算法如下:
size表示当前已经存放的元素的个数,由于插入的是一个元素,因此需要的最小容量是size+1,接着判断最小容量是否超出了数组的大小,超出则申请size+1的数组。
上面红色标记字体就是需要重点关注的地方,从上面描述的算法可以得出,当超出数组默认的大小后,每次添加一个新的元素后,都会申请新的数组,进行数组复制操作。为什么会出现这样的情况呢?
原因在于每次申请的新的数组容量都是size+1即新申请的数组容量都只够当前元素的添加,也就是每次申请的数组空间都只能满足当前需求,而没有考虑到今后是否还需要继续添加元素。
所以,minCapacity只是当前需要的最小容量,但是并不代表这就是申请的新的容量。那么多少才是合适的呢?
可以选择一个简单的算法,那就是每次申请原数组容量的1.5倍,
这个算法虽然比较简单,但是需要注意:
整数的加法是有可能出现溢出的,如minCapacity = size+1 以及上面的newCapacity,这两个变量都是有可能出现溢出的,因此在使用的时候需要进行判断。这也是平时我们在设计算法中如果使用到加法运算应该慎重考虑的地方。
总结
本文在上一讲的基础上针对数组扩容时每次申请size+1的容量导致超过初始默认容量后就需要一直不断的进行扩容操作,提出一种新的数组扩容算法,使其效率更高。