我们在实际工作中使用List情况非常多。
那么我们来看下ArrayList的 底层是如何实现的
其实ArrayList底层是一个Object 的 数组
我们来看下jdk中的源代码 如下
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//默认的Arraylist大小
private static final int DEFAULT_CAPACITY = 10;
//内部使用的空的object数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//Object数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//Object数组
transient Object[] elementData;
//数组的个数
private int size;
//有参构造方法 对elementData数组做初始化处理
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造,对elementData数组做做初始化处理
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
}
那么我们可以看到在new ArrayList() 或者 new ArrayList(20) 都会对其内部的elementData做初始化的处理
我们也看到elementData是属于Object [] 它是Object的数组类型
所以我们说ArrayList底层是一个数组类型的。
我们知道数组是不可变的,如果要操作数组只能去新建一个数组把原来的数据copy进来,再进行添加元素,那么我们在Arraylist中经常使用较多的方法有 add() ,它是怎么去操作的,我们来看下它的源码 如下
public boolean add(E e) {
//这个方法是使用到扩容操作
ensureCapacityInternal(size + 1); // Increments modCount!!
//elementData 赋值 siez 是默认的当前Arraylist的大小
//这个size有提供 size()方法,实际是获取当前Arraylist的一个数据元素的大小
//给elementData赋值操作
elementData[size++] = e;
return true;
}
那么在add的时候 是调用了 ensureCapacityInternal(size + 1); 这一个方法 我们来看它的源码
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
里面又调用了两个 方法 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
我们先看 calculateCapacity(elementData, minCapacity)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
这段代码是 判断 最小的增长个数是多少,如果第一次添加的话,elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA都是空的object数据,那么返回的是 默认的 DEFAULT_CAPACITY 这个值是10 上面有说明
如果不是第一次添加,则返回minCapacity,这个值是在size的基础上+1(这个值默认是0,每次添加一个元素,都会加1)
这个方法执行完毕,那么我们再看 要执行的方法是 ensureExplicitCapacity 。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
代码也很简单,这里有个判断,如果传入进来的minCapacity 大于 elementData数组的大小,那么这里又调用了 grow(minCapacity)方法,这个方法就是我们最终寻找的动态扩容的方法
private void grow(int minCapacity) {
// 原来数组的大小
int oldCapacity = elementData.length;
// 最新数组的大小 为 旧数组大小的1.5倍 (右移一位)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
这里就是对数组原来的大小进行判断,那么如果比原来的大小要大,则扩容
最后我们可以看到elementData 使用了数组的一个 copy的方法,把原来的数组内容扩容到新的数组里面去了,最终实现扩容的目的
好了,到此 ArrayList操作的一个添加的过程剖析完毕。相信看了之后能够明白 它的底层添加是如何操作的