ArrayList類集成了AbstractList類
ArrayList中有兩個構造方法(方法名相同,方法參數不同叫做重載),默認構造方法通過調用ArrayList(int)來事項ArrayList的創建,傳入的值為10


因為ArrayList類繼承了AbstractList類,其中super調用了父類的默認構造方法,父類的該方法為一個空的方法(只有方法的聲明,沒有方法的實現),因此這段代碼中最關鍵的是實例化了一個Object的數組,并將此數組付給了當前實例的elementData屬性,Object的大小為傳入的參數值,因此在調用空狗仔方法的時候,會創建一個大小為10的Object數組,因此可以看到ArrayList采用數組的方式來存放對象

當調用add方法時候,首先基于ArrayList中已有的元素數量+1,產生一個名為minCapacity的變量,然后比較此值和Object數組的大小,如果此值大于Object數組值,那么先將當前的Object數組復制給一個數組對象,接著產生一個新的數組的容量值,此值的計算方法為當前數組值*1.5+1,如果得出的容量值仍然小于minCapacity,那么就以minCapacity作為新的容量值,在得出這個容量值后,調用ArrayList.copyOf來生成新的數組對象,如果想調整容量的增長策略,可集成ArrayList并覆蓋ensureCapacity方法即可。
首先創建一個新的數組對象,該數組對象的類型和之前ArrayList中元素類型一直,如果是Object類型,則直接通過new Object[newLenth]的方式來創建,如果不是Object類型,則通過Array.newInstance調用native方法創建相同類型的數組,在創建完新的數組對象后,調用System.arraycopy通過native方法將之前數組中的對象復制到新的數組中
將元素直接插入指定的int位置,這個方法的實現首相要確保插入的位置是目前數組中存在的,之后還要確保數組的容量夠用,在完成這些動作之后,和add(E)的不同的地方就是他要將當前的數組對象進行一次復制,即將目前index以及其后的數據都往后挪動以為,然后才能將指定的index位置的賦值為傳入對象,可見這中方式要多付出一次復制數組的代價。
替換指定位置的對象,首先會檢查傳入的位置是否小于當前數組的長度,此方法的返回值為替換之前的當前位置的內容


實現方法和add方法相似
當執行此方法時候,ArrayList首先判斷對象是否為null,如果為null,則遍歷數組中已經有值的元素,并比較是否為null,如果為null則調用fastRemove來刪除相應位置的對象,fastRemove方法的實現方式為將index后的對象往前復制一位,并將數組中的最后一個設置為null,即釋放了對此對象的引用,此方法返回true或false
如果傳入元素不為null,唯一的不同在于通過E的equals來比較元素的值是否相同,如果相同則認為是需要刪除對象的位置,則調用fastRemove方法來完成刪除,此方法返回true或false
還提供了remove(index)方法來刪除指定的對象,此方法比remove(e)多了一個數組范圍的檢測,但少了對象位置的查找,因此性能會更好,此方法返回刪除的元素



傳入參數為數組中元素的位置,然后進行數組長度的驗證,然后返回數組中此位置的對象

Iterator方法有ArrayList的父類AbstractList實現,當每次調用iterate方法時,都會創建一個新的AbstractList內部類對象itr的實例,當調用此實例的hasNext方法時候,比較當前指向的數組的位置是否和數組中已有的元素大小相等,如相等則返回false,否則返回true
方法的實現為遍歷整個ArrayList中已經存在的元素,如果E為null,則直接判斷已有元素是否為null,如為null,則返回true,如E不為null,則通過E.equals進行判斷是否相等
IndexOf為從前往后查找
lastIndexOf為從后往前查找


在單線程運行的情況下,如果 Size = 0,添加一個元素后,此元素在位置 0,而且 Size=1;
而如果是在多線程情況下,比如有兩個線程,線程 A 先將元素存放在位置 0。但是此時 CPU 調度線程A暫停,線程 B 得到運行的機會。線程B也向此 ArrayList 添加元素,因為此時 Size 仍然等于 0 (注意哦,我們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然后線程A和線程B都繼續運行,都增加 Size 的值
線程不安全測試代碼
import java.util.ArrayList; import java.util.List; publicclass Demo implements Runnable { List<String> list1 = new ArrayList<String>(1);// not thread safe publicvoid run() { try { Thread.sleep((int)(Math.random() * 2)); } catch (InterruptedException e) { e.PRintStackTrace(); } list1.add(Thread.currentThread().getName()); } publicstaticvoid main(String[] args) throws InterruptedException { ThreadGroup group = new ThreadGroup("testgroup"); Demo t = new Demo(); for (inti = 0; i < 10000; i++) { Thread th = new Thread(group, t, String.valueOf(i)); th.start(); }
while (group.activeCount() > 0) { Thread.sleep(10); } System.out.println(); System.out.println(t.list1.size()); // it should be 10000 if thread safe collection is used. } } |
新聞熱點
疑難解答