增強for為什麼不能刪除集合裡的元素
1.先看看ArrayList物件呼叫iterator()返回的Iterator物件
public Iterator iterator() {
return new Itr();
}
123
2.再看看ArrayList中實現Iterator的內部類Itr
private class Itr implements Iterator {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
…
}
12345
cursor表示下一個返回元素的下標,可以理解成 遊標;lastRet表示上一次返回的元素下標。另ArrayList有個size屬性,表示ArrayList中的元素個數。
3.看迭代器的hasNext()方法
public boolean hasNext() {
return cursor != size;
}
123
hasNext() 的判斷條件是cursor != size. 只要沒遍歷到最後一個元素,就返回true.
4.下面是next()
public E next() {
…
int i = cursor; // cursor為當前需要返回元素的下標
…
cursor = i + 1; // cursor向後移動一個位置,指向下一個要返回的元素
return (E) elementData[lastRet = i]; // 對lastRet賦值,然後返回當前元素
}
1234567
5.現在看下例子
ArrayList list = new ArrayList();
list.add(“e1”);
list.add(“e2”);
Iterator var2 = list.iterator();
while(var2.hasNext()) {
String str = (String)var2.next();
if(“e1”.equals(str)) {
list.remove(“e1”);
}
}
12345678910
執行會報錯,這種操作是不被允許的。
6.解釋:
第一次 呼叫var2.hasNext(),此時滿足條件 cursor(0) != size(2),然後執行 var2.next(),此時 cursor=1
執行 list.remove(“e1”),此時,list的size將從2變為1當執行完第一次迴圈,進入第二次hasNext()判斷時,cursor=1而且size=1,導致Iterator認為已經遍歷結束,因此e2將被漏掉。此時,過程已非常清楚。list本有2個元素,Iterator第一次獲取元素時,程式刪掉了當前元素,導致list的size變為1。Iterator第二次獲取元素時,開心說到:”list一共只有一個元素,我已經遍歷了一個,easy,輕鬆搞定!”。
矛盾點在於:hasNext() 是根據已fetch元素和被遍歷物件的size動態判斷的,一旦遍歷過程中被遍歷物件的size變化,就會出現以上問題。
7.正確的姿勢,在使用迭代器遍歷的時候對集合元素進行增刪
將remove操作交給Iterator來處理,使用Iterator介面提供的remove操作。
List list = new ArrayList<>();
list.add(“e1”);
list.add(“e2”);
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if (“e1”.equals(str)) {
iterator.remove();
}
if ("e2".equals(str)) {
System.out.println("element 2 fetched");
}
}
1234567891011121314
執行結果:element 2 fetched 被正常列印出來。 那Iterator的remove()又是怎麼做的?下面是ArrayList中迭代器的remove方法。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet); // 呼叫ArrayList的remove移除元素,且size減1
cursor = lastRet; // 將遊標回退一位
lastRet = -1; // 重置lastRet
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
1234567891011121314
因為Iterator.remove()在執行集合本身的remove後,同時對遊標進行了 “校準”。
相關文章
- list增強for迴圈刪除元素報錯
- 阿里巴巴為什麼這樣強制從List中刪除元素阿里
- J2SE-刪除List集合元素
- 網路負面訊息如何刪除?為什麼不能直接刪除客戶投訴的負面資訊?
- JS刪除陣列裡的某個元素方法JS陣列
- jQuery為元素新增和刪除classjQuery
- 建立元素和刪除元素
- jQuery刪除元素jQuery
- jQuery 刪除元素jQuery
- win10開始裡的文件不能刪除怎麼辦 win10開始裡的文件無法刪除如何處理Win10
- 不能刪除DBLINK
- 【Java】增強for迴圈,三種迭代的能否刪除Java
- HashMap 之元素刪除HashMap
- 我們為什麼會刪除不了叢集的 Namespace?namespace
- JavaScript刪除陣列元素JavaScript陣列
- Lambda 表示式遍歷集合時用remove方法刪除list集合中滿足條件的元素問題REM
- 什麼樣的文章會被刪除?
- ArrayList元素的刪除(4種函式)函式
- Python列表刪除元素的方法有哪些?Python
- 根據陣列的值刪除元素陣列
- PHP 刪除陣列中元素的方式PHP陣列
- 刪除內聯元素之間的空隙
- Array · 刪除陣列中指定的元素陣列
- jQuery刪除具有指定文字的li元素jQuery
- u盤裡的檔案無法刪除 如何刪除u盤裡刪不掉的檔案
- linux的刪除檔案命令和強制刪除命令Linux
- JavaScript 刪除陣列指定元素JavaScript陣列
- JavaScript刪除array陣列元素JavaScript陣列
- 字典,元組,集合的增刪改查
- list中for迴圈刪除多個元素為何報錯?
- STL.vector容器刪除單個元素、部分元素、全部元素
- 死磕 java集合之ConcurrentHashMap原始碼分析(三)——刪除元素全解析(內含彩蛋)JavaHashMap原始碼
- 什麼是資料增強?
- 怎麼刪除我的電腦裡的onedrive_win10刪除onedrive資料夾的方法Win10
- Python 中刪除列表元素的三種方法Python
- PHP從陣列中刪除元素的方法PHP陣列
- 區塊鏈世界裡不能信什麼?區塊鏈
- JavaScript 刪除陣列重複元素JavaScript陣列