1. 程式人生 > >ArrayList原始碼理解

ArrayList原始碼理解

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]);
		}

輸出結果:
在這裡插入圖片描述