本人,小白中的小白,今天经历一场前所未有的面试,深受刺激,决定动手写文章,对所学内容进行输出。文章比较适合小白阅读还有希望高人指点。
这是我第一次写博客请大牛们多多指教,多多包容!
面试中提问到一个关于ArrayList的问题。谁都知道ArrayList底层是数组,并且会自动扩容。那面试官就问了,ArrayList是怎么扩容的?什么时候它会进行扩容?扩容多少?
文章目录
- 初始化 以及 扩容问题
初始化 以及 扩容问题
既然是扩容问题,二话不说,先看ArrayList源码。(扩容有关的方法)
private Object[] grow(int minCapacity) {
return this.elementData = Arrays.copyOf(this.elementData,this.newCapacity(minCapacity));
}
扩容嘛,当然是看grow方法,里面一个Arrays.copyOf方法即数组复制,就是创建一个新的数组长度为this.newCapacity(minCapacity),把老数组里面的内容复制到新数组中。
看copyOf方法的第二个参数,这个参数是int类型,就是新数组的长度。this.newCapacity(minCapacity)即调用自己的newCapacity方法,传递的参数是minCapacity,这个参数是添加元素到末尾之后的容量,即保证list中含有的最小容量minCapacity
以上代码需明确:
扩容就是复制数组,就是创建一个新的数组,然后把老数组的内容复制进新数组中。至于新的数组长度多少,全在newCapacity方法里面揭晓!
.
private int newCapacity(int minCapacity) {
//这里就是获取老数组的长度
int oldCapacity = this.elementData.length;
//这里就是扩容的关键代码。将数组长度增加原来的0.5倍!
int newCapacity = oldCapacity + (oldCapacity >> 1);
//扩充之后,还是小于minCapacity即:还是小于数组添加新元素之后所需的最小容量
if (newCapacity - minCapacity <= 0) {
if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(10, minCapacity);
} else if (minCapacity < 0) {
throw new OutOfMemoryError();
} else {
//还是小于minCapacity,那就minCapacity实际元素的个数,进行扩容。
return minCapacity;
}
} else {
return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
}
}
对上述代码简单描述:
- 明确该方法的作用,就是返回新数组的长度是多少。
- 数组一般是怎么扩容 oldCapacity + (oldCapacity >> 1)。直白点说就是:老数组长度+老数组长度的一半
- 当数组扩大了老数组的百分之50之后,有可能还是不够用,即newCapacity - minCapacity <= 0
此时分为两种情况讨论(要么老数组本来就是空的,要么就是扩容之后容量还是不够)
情况一:此时就为数组建立一个空数组,
this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
并且,为它创建一个初始容量大小为10的数组,或者如果所需的容量超过10那就以minCapacity为标准来创建大小(注意:该方法返回的是新数组长度的大小,要么返回10要么返回minCapacity)
return Math.max(10, minCapacity)
- 如果数组不为空,当然就是扩容后小于实际容量大小那就按照数组的实际容量return minCapacity
- 数组扩容之后,也满足了实际容量大小了。为什么不直接return newCapacity返回新长度呢。而是还要和2147483639这个数比较大小,如果超过了这个21374…这个数,那就返回hugeCapacity(minCapacity)。那我得看看这个方法,究竟是何方神圣!
return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
.
其实就那样啦,如果实际的容量大于了2147483639这个数,那就返回 2147483647。没啥没啥,不必惊讶
return minCapacity > 2147483639 ? 2147483647 : 2147483639
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) {
throw new OutOfMemoryError();
} else {
return minCapacity > 2147483639 ? 2147483647 : 2147483639;
}
}
总结数组扩容的过程:
1、如果数组为空的话,初始容量大小为10的数组,如果10不够用那就用实际容量大小
2、一般扩容,是增大原来数组的一半,如果不够用,那就用实际容量大小