ArrayList内部实现原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList内部实现原理相关的知识,希望对你有一定的参考价值。
ArrayList内部实现原理
首先,我们new
一个对象list集合
List<String> list = new ArrayList<>();
我们知道对象的创建离不开构造方法,因此我们查看ArrayList源码的时候先看其构造方法
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // non-private to simplify nested class access
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
通过源码我们发现在new ArrayList<>()
的时候,其实质是获得一个Object[]
数组;
因此ArrayList的本质就是一个数组
然后我们向元素中添加一个对象通过add()
方法,并查看add的源码
list.add("123");
private int size;
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
在add方法中调用了一个方法ensureCapacityInternal()
用来初始化容量
然后向数组的末尾添加了一个元素
接下来我们来看看这个ensureCapacityInternal()
方法的内部是如何实现的
private static final int DEFAULT_CAPACITY = 10;
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
很显然在ArrayList被创建的时候执行了this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
,因此if
语句是成立的,我们知道当我们第一次执行add("123")
的时候size=0
,因此该方法的参数是1。所以minCapacity=10
然后我们看ensureExplicitCapacity(minCapacity);
这个方法的内部。
protected transient int modCount = 0;
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
因为elementData
是一个null
的对象数组,所以elementData.length=0
,if
条件成立执行grow(minCapacity)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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);
}
因为minCapacity=0
,所以newCapacity=0
,导致if(newCapacity - minCapacity<0)
成立,结果newCapacity = minCapacity;
等于10;
MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;
可以认为MAX_ARRAY_SIZE
是一个无穷大的数,因此if (newCapacity - MAX_ARRAY_SIZE > 0)
语句不成立,elementData = Arrays.copyOf(elementData, newCapacity);
拷贝原数组到新数组,新数组长度为10;
当我们继续添加直到ArrayList
的size=10
,我们继续add
第11个对象的时候if (minCapacity - elementData.length > 0)
成立,
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
因此,当ArrayList容量存满的时候,会扩容为原来的3/2倍
通过内部原理可知,对于ArrayList的每次操作,当需要扩容的时候,每次扩容为当前长度的1.5倍,但是每次操作集合都需要进行数组的拷贝,此过程消耗资源,所以如果对于经常对集合进行添加删除操作的时候,不建议使用ArrayList
以上是关于ArrayList内部实现原理的主要内容,如果未能解决你的问题,请参考以下文章