【Java集合】ArrayList自动扩容机制,javaarraylist扩容
【Java集合】ArrayList自动扩容机制,javaarraylist扩容
目录
扩充容量的方法ensureCapacity。
Arrays.copyof()方法
总结:
扩充容量的方法ensureCapacity。
ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍加1,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容量minCapacity),而后用Arrays.copyof()方法将元素拷贝到新的数组。从中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。
// 确定ArrarList的容量。
// 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”
public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
//如果还不够,则直接将minCapacity设置为当前容量
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
// 添加元素e
public boolean add(E e) {
// 确定ArrayList的容量大小
ensureCapacity(size + 1); // Increments modCount!!
// 添加e到ArrayList中
elementData[size++] = e;
return true;
}
我们可以发现,在add方法中,每次添加元素,都会调用ensureCapacity方法来判断是否需要扩容,并且传入(size+1)这个参数,size参数为现在的ArrayList的容量,+1表明如果成功插入,容量将变为多少。也可以理解成:正确插入需要的最小容量minCapacity,我们可以看到ensureCapacity中传入的正是这个参数。
ensureCapacity方法中,首先判断oldCapacity(当前ArrayList容量)是否大于minCapacity,如果大于则说明容量足够,不做任何操作,跳出函数。若当前容量不足以容纳当前的元素个数,则设置 新的容量=“(原始容量x3)/2 + 1”,如果还不够,则直接将minCapacity设置为当前容量(保证这一次正好可以正确插入,下次再插入还得扩容。。)
最后调用Arrays.copyOf方法,传入旧的需要扩容的ArrayList 和 新的容量。
Arrays.copyof()方法
public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
很明显调用了另一个copyof方法,该方法有三个参数,最后一个参数指明要转换的数据的类型,其源码如下:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
这里可以很明显地看出,该方法实际上是在其内部又创建了一个长度为newlength的数组,调用System.arraycopy()方法,将原来数组中的元素复制到了新的数组中。
下面来看System.arraycopy()方法。该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。
总结:
ArrayList查找速度确实快,但是频繁的插入删除数据对于ArrayList来说效率就很低了,需要不停的复制、移动元素。
相关文章
- 暂无相关文章
用户点评