在Map或者Collection的時候,不要用它們的API直接修改集合的内容(否則會出現 java.util.ConcurrentModificationException 異常),如果要修改可以用Iterator的remove()方法,例如:
Java代碼
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZukHcvN2Xu92Yp9CXzV2Zh1WavwVbvNmLllXZ0lmL3d3dvw1LcpDc0RHaiojIsJye.gif)
- public void setReparation( Reparation reparation ) {
- for (Iterator it = this.reparations.iterator();it.hasNext();){ //reparations為Collection
- Reparation repa = (Reparation)it.next();
- if (repa.getId() == reparation.getId()){
- this.reparations.remove(repa);
- this.reparations.add(reparation);
- }
- }
- }
public void setReparation( Reparation reparation ) {
for (Iterator it = this.reparations.iterator();it.hasNext();){ //reparations為Collection
Reparation repa = (Reparation)it.next();
if (repa.getId() == reparation.getId()){
this.reparations.remove(repa);
this.reparations.add(reparation);
}
}
}
如上寫會在運作期報ConcurrentModificationException,可以如下修改:
Java代碼
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZukHcvN2Xu92Yp9CXzV2Zh1WavwVbvNmLllXZ0lmL3d3dvw1LcpDc0RHaiojIsJye.gif)
- public void setReparation( Reparation reparation ) {
- boolean flag = false;
- for (Iterator it = this.reparations.iterator();it.hasNext();){ //reparations為Collection
- Reparation repa = (Reparation)it.next();
- if (repa.getId() == reparation.getId()){
- it.remove();
- flag = true;
- break;
- }
- }
- if(flag){
- this.reparations.add(reparation);
- }
- }
public void setReparation( Reparation reparation ) {
boolean flag = false;
for (Iterator it = this.reparations.iterator();it.hasNext();){ //reparations為Collection
Reparation repa = (Reparation)it.next();
if (repa.getId() == reparation.getId()){
it.remove();
flag = true;
break;
}
}
if(flag){
this.reparations.add(reparation);
}
}
請問, 按照代碼一寫出現異常的原因是什麼啊?
為什麼使用 Iterator來删除集合裡面的資料就沒有異常呢?
轉:ConcurrentModificationException主要原因及處理方法
2007年04月18日 星期三 12:57
當使用 fail-fast iterator 對 Collection 或 Map 進行疊代操作過程中嘗試直接修改 Collection / Map 的内容時,即使是在單線程下運作, java.util.ConcurrentModificationException 異常也将被抛出。
Iterator 是工作在一個獨立的線程中,并且擁有一個 mutex 鎖。 Iterator 被建立之後會建立一個指向原來對象的單鍊索引表,當原來的對象數量發生變化時,這個索引表的内容不會同步改變,是以當索引指針往後移動的時候就找不到要疊代的對象,是以按照 fail-fast 原則 Iterator 會馬上抛出 java.util.ConcurrentModificationException 異常。
是以 Iterator 在工作的時候是不允許被疊代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來删除對象, Iterator.remove() 方法會在删除目前疊代對象的同時維護索引的一緻性。
有意思的是如果你的 Collection / Map 對象實際隻有一個元素的時候, ConcurrentModificationException 異常并不會被抛出。這也就是為什麼在 javadoc 裡面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
1 import java.util.*;
2
3 public final class MyTest
4 {
5 private static HashMap p_mapList = new HashMap(2);
6 private MyTest(){}
7 public static void init(){
8 // If only there are more than one element in Map,
9 // the ConcurrentModificationException will not be
10 // thrown.
11 p_mapList.put(new String("hello"),new String("world"));
12 p_mapList.put(new String("goto"),new String("hell"));
13 }
14 public static void clear() throws Exception{
15 Iterator pTmpKeys = null;
16 Long pTmpKeyLong;
17 pTmpKeys = p_mapList.keySet().iterator();
18 String pCurKey = null;
19 String pCurObj = null;
20 while(pTmpKeys.hasNext()){
21 pCurKey = (String) pTmpKeys.next();
22 pCurObj = (String) p_mapList.get(pCurKey);
23
24 p_mapList.put(pCurKey,null);
25 // You can not remove element in Map object directly.
26 //p_mapList.remove(pCurKey);
27 // But you can remove current element by iterator itself.
28 pTmpKeys.remove();
29
30 System.out.println(pCurKey + " removed.");
31 }
32 System.out.println(p_mapList.size() +
33 " entries left after iterator.");
34 pTmpKeys = null;
35 }
36 public static void main(String[] args)
37 throws Exception{
38 MyTest.init();
39 MyTest.clear();
40 }
41 }