三、擴容機制
四、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,因為見過兩種寫法都有的,以為是版本問題。看了原始碼才發現,都可以的。如果你不...