ArrayList的迭代器原始碼分析
阿新 • • 發佈:2018-12-26
呼叫ArrayList的iterator方法後會返回可以操作集合的迭代器。
這是就有結合和迭代器兩種方式可以操作元素。
如果返回迭代器後再集合操作元素會丟擲ConcurrentModificationException異常
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
這裡的checkForComodification方法就是檢測返回迭代器後,集合是否對元素進行操作:如 曾刪改 如果發生丟擲異常
moCount變數的作用 : 是記錄集合對元素的增刪改的次數。
exceptedmodCount變數作用:當迭代器返回時就將集合對元素修改的次數(modCount)賦值給此變數。
當返回迭代器後,如果集合再進行修改元素操作modCount會累加,當呼叫迭代器的方法對元素修改時,會首先呼叫checkForCoundification方法判斷modCount和ExceptedmodCount是否一樣,不一樣代表返回迭代器後,集合有進行了修改元素操作,所以就需要丟擲異常
至於為什麼要丟擲異常。我覺得沒有什麼意義,因為next方法有依靠size,elentData(應該是儲存元素的陣列)變數。
當外部類這些變數發生變化他也會跟著發生變化。沒有什麼安全隱患啊?
網路上說,當返回迭代器後,集合傳到迭代器資料,迭代器資料就固定了,也就是隻知道返回迭代器之前的集合元素。
再修改集合中的元素迭代器不知道。所以定義了併發修改異常。但原始碼中並不是這樣,而是隨外部類變化的變數。