ArrayList原始碼理解
阿新 • • 發佈:2018-11-19
LK決定最近擼一下常用集合原始碼,畢竟在專案裡主要用到的就是這些常用集合。要分析的集合原始碼主要有
- ArrayList
- LinkedList
- HashMap
- HashSet
- LinkedHashMap
一 繼承體系
建立ArrayList()物件,ctrl+T可以看到ArrayList繼承體系,主要繼續了AbstractList,AbstractCollection.實現了List, RandomAccess, Cloneable, java.io.Serializable介面。
二 建構函式理解
建構函式是平時使用ArrayList集合最常用的方法,ArrayLiat提供了三種構造器,指定大小的,空集合,以及集合作為引數的。
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); } }
public ArrayList() {
//建立預設空陣列
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) { //將集合轉換為陣列 elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) //陣列不為空進行陣列複製 elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }
三 動態擴容機制(核心)
java首先會判斷此時集合大小,超過會建立一個此時陣列1.5倍的陣列,擴容後的陣列不允許大於Integer.MAX_VALUE int型別最大值==,MAX_ARRAY_SIZE==最大陣列大小,即int型別最大值減去陣列自身所佔的8個位元組。
下面是自己實現的小型ArrayList
public class MyArrayList {
// 陣列大小
private int size;
// 建立一個初始值為10的陣列
private static Object[] enptyArray = new Object[10];
public void add(Object elementData) {
if (size < enptyArray.length) {
enptyArray[size++] = elementData;
} else {
// 這裡使用原始碼中的自動擴容方式,將新陣列擴容成原陣列1.5倍
int enptyArrayNewLength = enptyArray.length + (enptyArray.length >> 1);
// 建立擴容後的陣列
Object[] newEmptyArray = new Object[enptyArrayNewLength];
// 將原陣列中的元素複製到新陣列中
System.arraycopy(enptyArray, 0, newEmptyArray, 0, size);
// 在新陣列末尾新增新元素
newEmptyArray[size++] = elementData;
// 將新陣列的物件引用賦值給預設陣列
enptyArray = newEmptyArray;
}
}
// 獲取陣列大小
public int size() {
return size;
}
// 重寫toarray(),將擴容後的陣列複製到新陣列中,用於遍歷輸出
public Object[] toArray() {
Object[] Array = new Object[size];
System.arraycopy(enptyArray, 0, Array, 0, size);
return Array;
}
public static void main(String[] args) {
MyArrayList array=new MyArrayList();
array.add(1);
array.add(2);
array.add("");
array.add(3);
array.add(4);
System.out.println(array.size());
Object arrayNew[]=array.toArray();
for (int i = 0; i < array.size(); i++) {
System.out.println(arrayNew[i]);
}
執行結果:
四 ArrayList允許插入空元素
為驗證Arraylist能夠插入空元素,重寫其remove方法
// 刪除元素操作
public void removeElement(Object e) {
if (e == null) {
//遍歷找到空元素位置
for (int index = 0; index < size; index++) {
if (enptyArray[index] == null)
pubRemove(index);
}
} else {
//遍歷找到要刪除元素位置
for (int index = 0; index < size; index++) {
if (enptyArray[index] == e)
pubRemove(index);
}
}
}
private void pubRemove(int index) {
// TODO Auto-generated method stub
//指定複製元素數量
int indexNew = size - index - 1;
//複製從原集合中空元素後一位開始
System.arraycopy(enptyArray, index + 1, enptyArray, index, indexNew);
//將原陣列最後一位填入空元素
enptyArray[--size] = null;
}
//main方法中新增此程式碼
array.removeElement("");
System.out.println("刪除空元素後集合大小:" + array.size());
Object arrayNewList[] = array.toArray();
for (int i = 0; i < array.size(); i++) {
System.out.println(arrayNewList[i]);
}
輸出結果: