ArrayList底层采用数组来实现元素存储,与数组最大的不同点就在于可以实现自动扩容,通过阅读jdk的源码,发现对于这部分内容从1.6到1.8版本一直在改动。在1.6版本中,扩容实现代码newCapacity = oldCapacity + oldCapacity/2 +1;扩容容量为1.5倍加一;1.7中,采用newCapacity = oldCapacity +(oldCapacity>>1);改为移位运算,同时扩容容量变为1.5倍。下面看看1.8的源码。
通过源码可以发现,在进行扩容时,多出来了一个对minCapacity的处理,先看私有化的ensureCapacityInternal(int minCapacity)方法,如果在初始化时调用的是无参数的构造方法,则会对扩容参数和DEFAULT_CAPACITY(一个int型常量,值为10)进行比较。如果minCapacity小于10,则会自动将扩容参数增大到10。ArrayList内部的add(E e),addAll(Collection<? extends E> c)等相关方法均通过这种方式扩容。同时ArrayList还提供了一个public方法ensureCapacity(int minCapacity),可以主动调用进行扩容。如果依赖于默认的扩容实现,每一次扩容都会进行内存拷贝,在数据量较大时会有性能损失,这种情况下初始化参数设大或者调用此方法可以进行性能优化。可以注意到,同样,如果在初始化时调用无参构造方法,在调用该方法时,会对
minCapacity参数进行比较,如果小于10,则不会进行任何操作,即不会对10以下的主动扩容请求进行处理,而如果是调用的有参数构造方法,则没有此限制。