ArrrayList原始碼分析

2021-10-10 14:28:51 字數 3910 閱讀 4821

三、擴容機制

四、remove方法

transient object elementdata;
意味著arraylist裡面的物件都是用不可序列化物件陣列儲存的,因為陣列裡面存的是陣列的引用,而引用預設佔4位元組,由於這一特點,隨機查詢快。

private static final object empty_elementdata = {}; //空陣列例項

private static final object defaultcapacity_empty_elementdata = {};

預設建構函式,共享的空陣列例項 defaultcapacity_empty_elementdata

public arraylist()

// 對initialcapacity 進行判斷

public arraylist(int initialcapacity) else if (initialcapacity == 0) else

}// 建立乙個包含collection的arraylist

public arraylist(collection extends e> c) else

}

elementdata  儲存物件的陣列引用

size arrraylist裡面元素的個數

public boolean add(e e)

確保內部容量

private void ensurecapacityinternal(int mincapacity)

計算容量

private static int calculatecapacity(object elementdata, int mincapacity)

return mincapacity;

}確保明確的容量

private void ensureexplicitcapacity(int mincapacity)

增長容量

private void grow(int mincapacity)

private static int hugecapacity(int mincapacity)

流程:①第一次新增,size=0,因為初始化elementdata指向空陣列,第一次擴容容量為10,此時modcount+1, grow(10), 此時執行arrays.copyof() 方法進行陣列複製.string的hash預設為0②當陣列中長度已為10,陣列長度增加到 10+10>>1 =15,然後執行arrays.copyof() ,最後進行elementdata[size++] = e 賦值,返回true

arraylist本身有兩個remove方法

按指定索引位置刪除

public e remove(int index)

刪除第一次出現指定元素的資料

public boolean remove(object o)

} else

}return false;

}快速刪除

private void fastremove(int index)

arraylist內部類也有乙個remove方法,使用迭代器的remove在遍歷中刪除是正確的

換成2會報錯,在arraylist裡面實行迭代刪除,foreach迴圈本質其實就是iterator,當執行iterator.next()時,會觸發checkforcomodification

public e next() 

final void checkforcomodification()

而不用list.remove,而使用iterator,remove時會執行

expectedmodcount = modcount;

public void remove()  catch (indexoutofbound***ception ex) 

}

foreach在arraylist中本質**如下

public class tttt }}

}

流程:①當list新增兩個元素之後又,modcount變成2

②list.iterator(); 這一步return new itr(); itr類有三個內部屬性

int cursor; // index of next element to return

int lastret = -1; // index of last element returned; -1 if no such

int expectedmodcount = modcount; 把modcount賦給expectedmodcount

③iterator.hasnext() 判斷 return cursor != size;,此時cusor=0,size =2,返回true

④iterator.next(); 執行checkforcomodification,

if (modcount != expectedmodcount)

throw new concurrentmodificationexception();

},此時兩者均為2,肯定相等的,然後把cursor 賦值給i

public e next() 

if (i >= elementdata.length)

throw new concurrentmodificationexception();

cursor = i + 1; 此時cursor = 1

return (e) elementdata[lastret = i]; 此時lastret = 0 , 返回 elementdata[0],即1

}

⑤ list.remove

public boolean remove(object o) 

} else

}return false;

} private void fastremove(int index)

執行fastremove,index=0, nummoved=1,執行system.arraycopy,把當前陣列的1號位置元素複製到0號位置,此時elementdata為,最後給elementdata[1]賦值null。,此時elementdata,size為1。⑥ 後面再執行iterator.hasnext()

此時cursor = size = 1,執行一次

問題關鍵所在: if (modcount != expectedmodcount)

throw new concurrentmodificationexception();

},因為expectedmodcount只賦值過一次,而modcount進行remove一次,

modcount就會進行改變,單執行緒刪除倒數第二個不會發生異常。

當"1".equals(str)換成2時,modcount=3,expectedmodcount=2

spring原始碼分析 spring原始碼分析

1.spring 執行原理 spring 啟動時讀取應用程式提供的 bean 配置資訊,並在 spring 容器中生成乙份相應的 bean 配置登錄檔,然後根據這張登錄檔例項化 bean,裝配好 bean 之間的依賴關係,為上 層應用提供準備就緒的執行環境。二 spring 原始碼分析 1.1spr...

思科VPP原始碼分析(dpo機制原始碼分析)

vpp的dpo機制跟路由緊密結合在一起。路由表查詢 ip4 lookup 的最後結果是乙個load balance t結構。該結構可以看做是乙個hash表,裡面包含了很多dpo,指向為下一步處理動作。每個dpo都是新增路由時的乙個path的結果。dpo標準型別有 dpo drop,dpo ip nu...

redux原始碼分析(三) 原始碼部分

下面是每個部分的一些解讀 createstore apicreatestore reducer,initialstate enhancer 曾經非常好奇這個函式的第二個引數到底是initialstate還是enhancer,因為見過兩種寫法都有的,以為是版本問題。看了原始碼才發現,都可以的。如果你不...