1. 程式人生 > >Java集合框架:ArrayList擴容機制解釋

Java集合框架:ArrayList擴容機制解釋

1、java中ArrayList該類的定義

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 預設容量為10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 空陣列:用於呼叫帶有容量切容量為0時初始化elementData這個值
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 空陣列:用於呼叫空構造時初始化elementData這個值

     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     *陣列變數
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * arrayList的長度
     */
    private int size;
   //後面自己需要看原始碼
   ...
}

2、ArrayList描述

    ArrayList是一個繼承abstractList和實現List的介面的實現類。    ArrayList是以陣列實現的陣列佇列,允許重複。可以通過ArrayList來進行增加,刪除,修改,遍歷等操作。
    ArrayList可以說是一個動態陣列。動態的最好例子可以說就是ArrayList的底層是陣列,該陣列的長度可以根據實際需要不斷增加。

3、ArrayList的擴容機制

    3.1 對外提供的檢查是否需要擴容方法

public void ensureCapacity(int minCapacity) {
//判斷elementData是否是預設空陣列,如果不是minExpand為0,如果是minExpand=DEFAULT_CAPACITY=10
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY;
//如果我們預測的值比陣列elementData陣列的長度實際要大,需要擴容。只能說明我們需要更大容器的列表。
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }


3.2 內部實現的擴容機制

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//父類AbstractLisy生命的屬性

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//我們需要的長度比elementData的長度大,擴容
            grow(minCapacity);
}
 private void grow(int minCapacity) {
	// overflow-conscious code
	int oldCapacity = elementData.length;//獲取當前存放資料陣列的長度
	int newCapacity = oldCapacity + (oldCapacity >> 1);//擴容到原來陣列長度的1.5倍
	if (newCapacity - minCapacity < 0)//如果擴容到長度的1.5倍以後,仍然不夠用,直接將我們預計的值作為擴容長度
		newCapacity = minCapacity;
	if (newCapacity - MAX_ARRAY_SIZE > 0)//擴容上限最大值為Integer的最大值-8,如果超過這個最大值,使用下面的方法
		newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: 
	elementData = Arrays.copyOf(elementData, newCapacity);//使用陣列Arrays的copyOf()進行擴容,每次擴容都採用System.arrayCopy()複製到新陣列的 
}
private static int hugeCapacity(int minCapacity) {//如果擴容超過Integer.MAX_VALUE-8,程式碼會走該方法 
	if (minCapacity < 0) // overflow throw new OutOfMemoryError(); 
	//如果我們預測的長度比Integer.MAX_VALUE-8大,最後取Integer.MAX_VALUE。 
	return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE : MAX_ARRAY_SIZE; 
}

4、ArrayList遍歷方式

                List<String> testList = new ArrayList<String>();
		testList.add("11");
		testList.add("21");
		testList.add("31");
		testList.add("41");
		testList.add("51");
		testList.add("61");
		testList.add("71");
		/**
		 * for迴圈遍歷
		 */
		for(int index=0;index<testList.size();index++){
			System.out.println(testList.get(index));
		}
		System.err.println("===========foreach===========");
		/**
		 * foreach遍歷
		 */
		for(String index:testList){
			System.out.println(index);
		}
		System.err.println("===========Iterator===========");
		/**
		 * 迭代器Iterator
		 */
		Iterator<String> iterator = testList.iterator();
		while(iterator.hasNext()){
			System.err.println(iterator.next());
		}
		

5、ArrayList和vector比較

普及:什麼是執行緒安全什麼是執行緒不安全

   執行緒安全就是多執行緒訪問時,採用了加鎖機制,當一個執行緒訪問該類的某個資料時,進行保護,其他執行緒不能進行訪問直到該執行緒讀取完,其他執行緒才可使用。不會出現資料不一致或者資料汙染。

    執行緒不安全就是不提供資料訪問保護,有可能出現多個執行緒先後更改資料造成所得到的資料是髒資料。 如圖,List介面下面有兩個實現,一個是ArrayList,另外一個是vector。 從原始碼的角度來看,因為Vector的方法前加了,synchronized 關鍵字,也就是同步的意思,sun公司希望Vector是執行緒安全的,而希望arraylist是高效的,缺點就是另外的優點。

1、Vector每次擴容都是請求其大小的2倍空間,而ArrayList是1.5倍

2、Vector還有一個子類Stack