
ArrayList是java中最常用的集合類之一,它的內部實現是基于數組,因此ArryList可以根據索引實現隨機訪問。ArryList繼承了AbstractList類,并且實現了List, RandomAccess, Cloneable接口。下面詳細分析一下ArrayList的實現,下面的分析是基于JDK1.8版本。
ArrayList對象創建
ArryList有三個構造函數:
//創建一個默認大小的ArrayListpublic ArrayList() //創建一個initialCapacity大小的 ArrayListpublic ArrayList(int initialCapacity) //使用其他Collection對象,創建arrayListpublic ArrayList(Collection extends E> c)
下面具體分析一下,每個構造方法是如何創建一個ArrayList對象,在深入構造方法之前,先看一下ArrayList幾個重要的成員變量:
//實際存儲數據的數組transient Object[] elementData; //列表實際存儲數據元素的個數private int size;//定義在AbstractList類中,//表示了隊列結構修改的次數,主要是當隊列大小發生變化時,//記錄變化次數protected transient int modCount = 0;//用于表示空實例的空數組對象實現private static final Object[] EMPTY_ELEMENTDATA = {};//表示創建默認大小的ArrayList實例,//主要是于EMPTY_ELEMENTDATA做區別,//個人認為EMPTY_ELEMENTDATA表示空ArrayList//DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示是//默認大小的ArrayList,沒有本質上的區別private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
注意:對modCount字段用法說明參考ArrayList實現分析(二)——常用操作和ConcurentModificationException異常
在熟悉了上面的幾個字段,下面先看第一個構造函數:ArrayList()
少說廢話,先看東西:
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
從代碼上就可以直接看到了DEFAULTCAPACITY_EMPTY_ELEMENTDATA的用法,把它賦值給了elementData,也就是相當于
elementData = {},創建了一個包含零個元素的數組。
第二個構造函數:ArrayList(int initialCapacity) ,同樣先看東西:
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); }}
在構造方法中,根據傳入的initialCapacity值分別進行不同的操作,如果是大于0,那么直接創建一個initialCapacity大小的數組對象,如果是等于0,那就使用EMPTY_ELEMENTDATA,這里就是使用上面說的EMPTY_ELEMENTDATA這個成員變量賦值,主要是為了代碼描述的更清晰;如果是小于0就拋出異常。
第三個構造函數:ArrayList(Collection extends E> c)
public ArrayList(Collection extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { //c.toArray might (incorrectly) not return Object[](see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData,size,Object[].class); } else { //用空素組給elementData賦值 this.elementData = EMPTY_ELEMENTDATA; } }
使用這個構造函數,首先是講傳入的集合對象c通過toArray()方法把c轉換為Object數組類型賦值給elementData,這里還增加了一個判斷,就是判斷賦值后的elementData大小是否為0,如果是0表示,傳入的集合對象c包含0個元素,那么使用EMPTY_ELEMENTDATA給elementData復制,如果傳入的集合對象c不為空,那么需要再對elementData的實際類型進行判斷,因為根據源碼中注釋,在執行c.toArray()的時候,可能返回的類型不是 Object[].class,這是jdk的bug(經過查閱,該bug在jdk9已經修復),因此這里需要再次判斷一下elementData的類型是否是Object[],如果不是,那么需要利用elementData當前的值,重新創建一個Object[]類型的數組,并用 elementData指向新的數組地址。
注意Arrays.copyOf(elementData, size, Object[].class)方法的作用是使用elementData數組,創建一個新的數組,該數組的大小是size,類型是Object[].class
本文先介紹ArrayList的創建過程,下一篇文章,重點分析一下ArrayList的常用操作。