一、關(guān)于remove
- 如果是remove(int index) 會(huì)先調(diào)用
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
這里有我們熟悉的IndexOutOfBoundsException數(shù)組越界異常赠尾;
- 如果是remove(Object o) 會(huì)轉(zhuǎn)化成數(shù)組下標(biāo)調(diào)用
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,numMoved);
elementData[--size] = null; // clear to let GC do its work
}
最終調(diào)用System.arraycopy力穗,以移動(dòng)后續(xù)數(shù)據(jù)覆蓋之前數(shù)據(jù)的方式實(shí)現(xiàn)刪除。
二气嫁、關(guān)于保存數(shù)據(jù)的實(shí)體
transient Object[] elementData;
之所以定義成transient是因?yàn)榈贝埃琫lementData默認(rèn)初始化長度是10(DEFAULT_CAPACITY),當(dāng)實(shí)際長度不足容量時(shí)寸宵,比如2崖面,則后8個(gè)沒存實(shí)際數(shù)據(jù)的位置是不會(huì)被序列化的。
三邓馒、關(guān)于forEach遍歷時(shí)
- 實(shí)際上for( : ) 是先會(huì)調(diào)用內(nèi)部類Itr的hasNext判斷是否有下個(gè)元素嘶朱,
之后調(diào)用next()取值給for中的變量蛾坯。 - 這里要注意光酣,在next時(shí)會(huì)調(diào)用
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
其中modCount每次對(duì)數(shù)組操作都會(huì)++,記錄操作次數(shù)脉课。
而在迭代器遍歷的過程中救军,一旦發(fā)現(xiàn)這個(gè)對(duì)象的mcount和迭代器中存儲(chǔ)的mcount不一樣那就拋異常财异。
這就是為什么我們循環(huán)遍歷中第二次調(diào)用remove等操作會(huì)異常的原因。
Fail-Fast 機(jī)制在ArrayList,LinkedList,HashMap中都會(huì)看到唱遭。
- modCount是定義在父類AbstractList.java中
protected transient int modCount = 0;
而expectenModCount定義在私有內(nèi)部類(迭代器的實(shí)現(xiàn))Itr中
int expectedModCount = modCount;