ArrayList的介紹
- ArrayList是List接口下的一個實現類,它可以動態的修改數組。
- 可以加入null,並且可以加入多個。
- 是由數組來實現存儲數據的。
- ArrayList基本等同於Vector,但是ArrayList是線程不安全的。
- ArrayList中維護了一個Object類型的數組elementData。
使用無參構造器創建ArrayList數組時的擴容(一)
public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
for (int i = 1; i < 11; i++) {
arrayList.add(i);
}
arrayList.add(100);
arrayList.add(200);
arrayList.add(300);
arrayList.add(400);
}
}
ArrayList arrayList = new ArrayList();
使用無參構造函數創建對象,先會創建一個空的elementData數組
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
(第一次進入add添加數字)for循環添加數字的時候,會首先進行一個裝箱操作。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
然后進入ArrayList類的add方法。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
add方法中首先判斷是否需要擴容,進入ensureCapacityInternal方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//第一次進入該方法時,兩個數組相同,if判斷為true
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
//private static final int DEFAULT_CAPACITY = 10;
//將兩者中的大的那個賦給minCapacity,傳入的minCapacity為1,經過賦值操作后,變為了10
}
ensureExplicitCapacity(minCapacity);
}
進入ensureExplicitCapacity方法確認是否需要擴容。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//此時minCapacity大小為10,數組長度為0,所以if判斷為true,進入grow真正的擴容方法
grow(minCapacity);
}
進入grow擴容。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
//>>右移運算相當於除以2
//oldCapacity=newCapacity=0
if (newCapacity - minCapacity < 0)
//if判斷為true,newCapacity的值變為10
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);
//進行數組的拷貝
}
依次返回后,將數據存入數組下標為0的地方。然后執行size++。
執行完上述操作后,集合的大小就變為了10,並且可以看到在0的位置存入了數據。
實際上第一次沒有真正用到1.5倍的擴容。
使用無參構造器創建ArrayList數組時的擴容(二)
第二次進入for循環的add方法時,在ensureCapacityInternal方法中,if判斷為false,直接進入ensureExplicitCapacity方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
//此時傳入的參數為數組中數據個數多少再加1,minCapacity=2
}
ensureExplicitCapacity方法中,不進入grow。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//minCapacity為2,elementData.length為10,不進入grow方法
grow(minCapacity);
}
返回后,將數據存入下標為1的地方。執行size++。
重復上述操作,直到for循環結束,存入十個數據。
使用無參構造器創建ArrayList數組時的擴容(三)
執行arrayList.add(100);也先進行裝箱操作。
再進入add,直到進入方法ensureExplicitCapacity.
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//此時數組元素已滿,minCapacity的值為11,大於數組的長度,所以要進入grow方法,進行擴容
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);
}
在grow方法中,將數組長度10賦值給oldCapacity。
新的數組容量newCapacity為原來數組容量的長度10加上,原數組長度除以2的值5,所以最后newCapacity的大小為15。
兩個if判斷都為false,最后執行Arrays.copyOf。
擴容后的數組大小為15。
使用有參構造器創建ArrayList數組時的擴容(一)
public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(8);
for (int i = 1; i < 9; i++) {
arrayList.add(i);
}
arrayList.add(100);
arrayList.add(200);
arrayList.add(300);
arrayList.add(400);
}
}
創建對象時,直接創建一個指定大小的數組。
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);
}
}
然后進入for循環,先裝箱,再進入add方法——ensureCapacityInternal方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
if判斷為false,直接進入ensureExplicitCapacity。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
minCapacity的值為1,數組長度為8。if判斷為false,返回,加入數據,size++。
使用有參構造器創建ArrayList數組時的擴容(二)
執行arrayList.add(100);
經過add——ensureCapacityInternal,直接進入ensureExplicitCapacity。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
minCapacity的值為9,elementData.length的值為8,進入grow方法擴容。
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);
}
oldCapacity=8
newCapacity=8+4=12
不進入if,執行拷貝,擴容成功。