一、關(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)?,elementData默認(rèn)初始化長(zhǎng)度是10(DEFAULT_CAPACITY),當(dāng)實(shí)際長(zhǎng)度不足容量時(shí),比如2,則后8個(gè)沒(méi)存實(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ù)。
而在迭代器遍歷的過(guò)程中,一旦發(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;