本文共 1787 字,大约阅读时间需要 5 分钟。
ArrayList是Java中比较常用的一个类,它是基于数组实现,非线程安全,可快速随机访问List中的元素。
ArrayList具有动态扩容的机制,每次在添加元素时,都会判断容量是否够用,如果不够用,则需要扩容。
JDK1.8中,ArrayList的初始容量为0,第一次添加元素时,会将容量设置为10,如果容量不够,则每次会扩大50%
扩容代码如下:
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
其中:
int newCapacity = oldCapacity + (oldCapacity >> 1);
容量被扩充为原容量的1.5倍,oldCapacity>>1,右移一位,即:oldCapacity除以2
elementData = Arrays.copyOf(elementData, newCapacity);
用Arrays的copyOf方法拷贝原数组内容,并设置新的长度。
可以看到ArrayList扩容需要做一次数组拷贝,如果是反复扩容,肯定会对程序的运行效率产生影响。所以在初始化ArrayList的时候,尽量设置初始化容量,避免其扩容。
测试代码:
final int count = 20 * 100000; Listlist = new ArrayList<>(); long begin = System.currentTimeMillis(); for(int i = 0; i < count ; i++) { list.add(i); } System.out.println("没有设置ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms"); list = new ArrayList<>(count); begin = System.currentTimeMillis(); for(int i = 0; i < count ; i++) { list.add(i); } System.out.println("设置了ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms");
执行结果:
没有设置ArrayList初始容量: 89 ms
设置了ArrayList初始容量: 18 ms
转载地址:http://nqaxa.baihongyu.com/