1.迭代器使用
Iterator(迭代器)給我們提供了一種遍歷序列的方式,其中主要關於以下幾種方法:
1.iterator()方法,返回一個Iterator對象。
2.next()方法,獲取迭代器的下一個元素,並會向后移動一個單位(注:初次調用next()會返回序列中的第一個元素)
3.hasNext()方法,判斷迭代器是否還有下一個元素(不會移動迭代器)
4.remover()方法,刪除當前的迭代器所指向元素,一般與next()方法連用
Iterator遍歷序列實施操作示例:
Iterator iter = subjects.iterator();//subjects為字符串序列 while(iter.hasNext()){ subject = iter.next(); if(subject.startsWith("6.")){//將以6.開頭的字符串從序列中移除 iter.remove(); } }
foreach語句格式:
for(元素類型type 元素變量value : 遍歷對象obj) {
引用value的語句;
}
2.foreach過程分析
foreach內部調由迭代器實現,但是當需要刪除序列元素時,foreach循環會發生錯誤
如:
分析:
ConcurrentModificationException異常
Iterator next方法實現源碼:
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(); }
在next方法中首先調用了checkForComodification方法,該方法會判斷modCount是否等於expectedModCount,不等於就會拋出java.util.ConcurrentModificationExcepiton異常。
注:modCount是ArrayList的一個屬性,繼承自抽象類AbstractList,用於表示ArrayList對象被修改次數(add、remove、clear、ensureCapacityInternal均會改變modCount值)。在創建Iterator的時候會將modCount賦值給expectedModCount,之后expectedModCount不再改變。設置該檢查的目的是為了阻止程序員在不允許修改的時候修改對象,Iterator 被創建之后會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變。 當索引指針往后移動的時候就找不到要迭代的對象,所以禁止迭代時修改對象,於是會拋出錯誤。
在執行next方法時,將會檢查modCount與expectedModCount值,由於foreach方法中,其內部由iterator實現,也會調用next()方法,但是,每次刪除元素時均會改變modCount值,因此,調用序列自身的remove()方法后再次調用next()方法時,經檢查modCount != expectedModCount,因此拋出ConcurrentModificationException異常
然而,在使用迭代器時,對迭代中的元素進行刪除並不會拋出錯誤,原因是:在iterator.remove()方法中,同樣調用了ArrayList自身的remove方法,但是調用完之后並非就return了,而是expectedModCount = modCount重置了expectedModCount值,使二者的值繼續保持相等。同時,Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性,不會導致索引指針移動時找不到迭代對象。
下面使用迭代器的語句同樣會拋出ConcurrentModificationException異常:
Iterator iter = subjects.iterator(); while(iter.hasNext()){ subject = iter.next(); if(subject.startsWith("6.")){ subjects.remove(subject);//僅將iter.remove()更改為subjects.remove(subject) } }
可以看出,異常確實是由迭代器在迭代過程中拋出
參考: