目录
1、结果
此文章基于Jdk1.8,以及无参构造函数来的。1.7我粗略看了一下啊,基本也是这样,没仔细看,只是不敢确保。
初始大小 | 加载因子 | 扩容倍数 | 底层实现 | 是否线程安全 |
---|---|---|---|---|
0 | 1 | 旧容量+旧容量右移一位 即 a+(a/2) | Object数组 | 线程不安全 |
2、分析
2.1、初始大小
看下相关源代码
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
从源代码得知,默认是10,网上不少朋友也都说是10,但是笔者个人认为,ArrayList的初始容量是0,笔者是从看无参构造的出来的。
无参构造:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
无参构造的相关数组声明:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // non-private to simplify nested class access
从上述代码可知:
在我们List<String> list = new ArrayList<>()的时候,此时的list的底层是一个
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {},初始容量为0;
至于大家所说的默认为10,是因为往ArrayList第一次添加元素的时候,走了一次扩容
将 数组elementData的容量扩充为10;
无参构造首次扩容dubug图:
2.2、加载因子
加载因子的系数小于等于1,意指 即当 元素个数 超过 容量长度*加载因子的系数 时,进行扩容。
eg:加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
minCapacity : 往ArrayList添加a的时候,添加成功时,elementData数组应该拥有的容量。
grow(int minCapacity) :是扩容函数;
比如当前list里面已经有10个元素了。那么再执行list.add(a);
此时minCapacity的值就是11;
从上述代码可知:当 minCapacity > elementData 长度时,进行扩容。
2.3、扩容倍数
先看扩容函数源代码:
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必须是整数。
比如:第一次扩容:应该是 0 + 0/2 = 0 ,
然后通过 if (newCapacity - minCapacity < 0) newCapacity = minCapacity;将默认值10 赋值给newCapacity。所以无参构造第一次扩容到10;
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//这一步比较大小,返回最大的。
//无参构造,第一步添加元素时,将默认值10返回给minCapacity
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
第二次扩容:是 10 + 10/2 = 15;
第三次扩容: 15 +15/2 = 22; 注意15/2 = 7 ,不是7.5。
通过第三步扩容可以得知,扩容倍数不是1.5倍。实际上是 a = a+a/2。当a 为偶数时,才是1.5倍。
2.4、底层实现
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // non-private to simplify nested class access
从这两块代码就可以知道是Object数组;
如果有不同理解,欢迎留言评论,共同讨论,如果觉得帮到了你,并且值得你打赏,并且你愿意打赏,请打赏一下,作为创作的动力,多少都行。最后恭祝各位学业有成,事业有成。