以Java8为版本分析
在ArrayList中,关键变量有两个。
//存储对象的数组
transient Object[] elementData;
//数组长度
private int size;
当然,还有下面的一些变量
//默认容量
private static final int DEFAULT_CAPACITY = 10;
//空对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空对象数组,在初始化的时候有用。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
有三种初始化的方法。
向ArrayList中添加数据的操作有四中,分别为:
其对应的源代码如下:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
非常简单的一段代码,其流程如下:
那么,关键性的代码就在于ensureCapacityInterna操作了。我们看看它做了什么。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
继续跟踪
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
我们接下来看扩容操作的逻辑。
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);
}
解释如下:
采用这样扩容方法的好处是什么呢?我们想想,党我们一直往里塞数据的时候,容量会增长的越来越快(ArrayList以为我们贪得无厌了~),同样,这样的坏处就是,党我们添加到最后的时候,我们可能申请了很大的空间,但是只往里加多了一个数据,这样就造成了浪费。不过,这都是小事~~~
public boolean addAll(int index, Collection extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
由于那两个方法是native方法,我们在这里就不说了。
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
在知道ArrayList中使用的数据结构以及如何添加数据操作之后,明显对ArrayList理解了很多。