遍歷List 同時 remove 元素

lostinai發表於2013-08-24
  1. List<Integer> list = new ArrayList<Integer>();  
  2. list.add(1);  
  3. list.add(2);  
  4. list.add(3);  
  5. list.add(4);  
  6. list.add(5);  
  7. list.add(6);  
  8.   
  9. for (Iterator<Integer> iter = list.iterator(); iter.hasNext();)  
  10. {  
  11.     int i = iter.next();  
  12.     if (i == 3)  
  13.     {  
  14.         list.remove(i);  
  15.     }  
  16. }  

執行上邊的程式碼就會報錯:


API中此異常的解釋:當方法檢測到物件的併發修改,但不允許這種修改時,丟擲此異常。

原因:

Iterator 是工作在一個獨立的執行緒中,並且擁有一個 mutex 鎖。 Iterator 被建立之後會建立一個指向原來物件的單鏈索引表,當原來的物件數量發生變化時,這個索引表的內容不會同步改變,所以當索引指標往後移動的時候就找不到要迭代的物件,所以按照 fail-fast 原則 Iterator 會馬上丟擲 java.util.ConcurrentModificationException 異常。

所以 Iterator 在工作的時候是不允許被迭代的物件被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除物件, Iterator.remove() 方法會在刪除當前迭代物件的同時維護索引的一致性。


網上找的解決方法:

1.倒過來遍歷list

  1. for (int i = list.size()-1; i >=0; i--)  
  2. {  
  3.     int item = list.get(i);  
  4.     if (item == 3)  
  5.     {  
  6.         list.remove(item);  
  7.     }  
  8. }  

2.每移除一個元素以後再把i移回來

  1. for (int i = 0; i < list.size(); i++)   
  2. {  
  3.     int item = list.get(i);  
  4.     if (item == 3)  
  5.     {  
  6.         list.remove(item);  
  7.         i=i-1;  
  8.     }  
  9. }  

3.使用iterator.remove()方法刪除

  1. for (Iterator<Integer> iter = list.iterator(); iter.hasNext();)  
  2. {  
  3.     int item = iter.next();  
  4.     if (item == 3)  
  5.     {  
  6.         iter.remove();  
  7.     }  
  8. }  


相關文章