ArrayList实例及源码解析
简介
Java.util.ArrayList类是一个动态数组类型,可以随时从链表中添加或删除一个元素。ArrayList实现了List接口并且可以动态改变大小的。当我们不知道数据元素的个数时,就可使用ArrayList;如果知道数据元素个数,就可以直接用数组。
实例
在此通过实例+分析源码来明白在舒适化ArrayList和使用其方法时底层是如何实现的
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(-200);
System.out.println(list.get(10));
int i = 10;
for (int j = 0;j <= i;j++){
list.add(j);
}
以上面实例对Arraylist进行剖析。
源码解读
List<Integer> list = new ArrayList<>();
首先进行arraylist初始化,此时调用arraylist的构造方法
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
此时构造方法会构建一个空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
使用此方法进行初始化,arraylist是一个空数组,并无长度,长度赋值实在第一次调用add()时,下面hi进行讨论。除了上述方法进行初始化外,还有一个方法可以进行初始化。
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
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);
}
}
带有容量参数构造方法进行初始化,在此不探讨
list.add(1);
/*
在第一次进行add时,此时arraylist的size是0
因为我们这里的数据类型是Integer,会先进行判断所add的这个数据是否在Integer范围之内
若所add数据在Integer范围之内,会return在缓存中的值,反正,则会创建一个Integer对象。
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
//调用add方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//确定arraylist容量
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/*
calculateCapacity方法,两个参数,数组大小,最小所需容量0
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return 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);
}
总结:
在使用无参数构造方法进行ArraylList初始化时,此时list
容量为空,容量第一次变化是在调用add方法时进行容量初始化,默认容量大小是10,在每一次进行调用add方法时都会判断当前list容量是否满足添加数据,若容量不足以进行接下来数据的添加,则进行扩容,下一次扩容为原始容量的1.5倍。