1. 程式人生 > 其它 >Java-ArrayList

Java-ArrayList

ArrayList(部分內容摘取於:優秀參考文章

【介紹】

ArrayList就是動態陣列,用MSDN中的說法,就是Array的複雜版本,它提供了動態的增加和減少元素,實現了ICollection和IList介面,靈活的設定陣列的大小等好處

ArrayList封裝了一系列操作,如增刪改查,對比使用傳統的陣列方便了很多,因為java程式碼已經替我們寫好了,我們直接用即可。


【使用】

一、構造方法:

(1)無參構造器:返回一個初始容量為0的空列表,擴容是在第一次add的時候進行的

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

(2)傳入一個 int型別 的有參構造器:返回一個以你傳入的引數作為初始容量的空列表

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

(3)構造一個包含指定 collection 的元素的列表,這些元素是按照該 collection 的迭代器返回它們的順序排列的。

public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}

二、常用方法:

以實現List介面為例:


【底層操作機制原始碼分析】

(1)ArrayList中維護了一個Object型別的陣列 elementData

(2)當建立ArrayList物件時,如果使用的是無參構造器,則初始elementData容量為0,第一次add,則擴容為10,如果後續再次需要擴容,則擴容為原容量的1.5倍(看原始碼,有移位操作)

(3)如果使用的是指定大小的構造器,則初始容量為指定的大小,如果後續需要擴容,則擴容為1.5倍。

ArrayList類的相關方法和屬性:

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	//無參構造器:elementData被賦值為一個空的物件陣列
}

transient Object[] elementData; //transient(短暫的意思):對於transient 修飾的成員變數,在類的例項物件的序列化處理過程中會被忽略。
private static final int DEFAULT_CAPACITY = 10; //欄位意思:預設容量,值為10
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //就是一個空的物件陣列
private int size; //初始值為0

無參構造器第一次 add:

public boolean add(E e) {
    modCount++;  //該欄位表示list結構上被修改的次數
    add(e, elementData, size);
    return true;
}


private void add(E e, Object[] elementData, int s) {
	//判斷元素個數 size 是否等於陣列elementData的長度,如果相等,則進行擴容操作
    if (s == elementData.length) //s=size=初始值0;elementData陣列一開始也是空陣列,長度為0
        elementData = grow();
    elementData[s] = e;  //將元素新增進陣列中
    size = s + 1;  //新增完成後,size加1
}

private Object[] grow() {
    return grow(size + 1); //傳入size + 1 = 0+1 = 1
}

private Object[] grow(int minCapacity) { //最小容量為 1(size + 1)
    int oldCapacity = elementData.length; //舊容量為空陣列長度0
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次add,這裡都是fasle,進入else
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth */
                oldCapacity >> 1           /* preferred growth */);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else { //返回一個新的物件陣列給elementData,容量是DEFAULT_CAPACITY, minCapacity這兩個的最大值,故第一次擴容,容量是10
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

無參構造器第十一次add:

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    // assert oldLength >= 0
    // assert minGrowth > 0

    int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
    if (newLength - MAX_ARRAY_LENGTH <= 0) {
        return newLength;
    }
    return hugeLength(oldLength, minGrowth);
}

有參構造器:

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

注意使用有參構造器傳入引數0和使用無參構造器的區別:

//它們的擴容機制不太一樣
    List list2 = new ArrayList(0); //this.elementData = EMPTY_ELEMENTDATA;
    List list3 = new ArrayList(); //this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

擴容方法:(Arrays.copyOf()方法詳解-jdk1.8)

return elementData = Arrays.copyOf(elementData, newCapacity);

modCount引數:

參考文章:https://blog.csdn.net/u012926924/article/details/50452411