先来看一道笔试题:
下面的ArrayList会扩容几次?
ArrayList<String> arrayList = new ArrayList<String>(20);
我们先看一下源码的动态扩容机制是如何实现的。下面以jdk1.7为例:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 右移一位,转化为10进制即为除以2
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 第一次添加元素时,oldCapacity为0,即newCapacity为0,此时走此分支
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倍。且通过位移操作实现,比直接算术运算效率更高。
我们回过头来再看开头的笔试题,ArrayList的默认大小是10,
private static final int DEFAULT_CAPACITY = 10;
因此我们可以草率的下结论答案应该是2次。但是我们还要仔细看一下问题的根本:什么情况下才会采用动态扩容机制?
通过查看代码可以发现只有在容量不够的情况下才会采取动态扩容机制。而创建对象时指定容量为20,是不需要扩容的,
再来看一下构造方法的源码,
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
我们可以看到直接将传过来的初始容量传递给底层实现的数组。并没有什么扩容机制。
最后,我们再来公布开头问题的答案。经过分析,那就是扩容次数为0。