解决ArrayList的ConcurrentModificationException

有一个List<String> list, 现在需要将其清空[不使用removeAll()方法], 很容易在for循环的remove中出现ConcurrentModificationException.

 1 package cn.iwoo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.List;
 6 
 7 public class ListRemoveTest {
 8     public static void main(String[] args) {
 9         ListRemoveTest test = new ListRemoveTest();
10         
11         System.out.println("-1-使用jdk5.0以后的增强for循环去remove");
12         List<String> list = test.buildList();
13         try {
14             for (String str : list) {
15                 list.remove(str);
16             }
17         } catch (Exception e) {
18             // java.util.ConcurrentModificationException
19             e.printStackTrace(); 
20         }
21 
22         System.out.println("-2-使用Iterator的remove");
23         list = test.buildList();
24         try {
25             Iterator<String> iterator = list.iterator();
26             while (iterator.hasNext()) {
27                 iterator.remove();
28             }
29         } catch (Exception e) {
30             // java.lang.IllegalStateException
31             e.printStackTrace();
32         }
33 
34         System.out.println("-3-iterator遍历+list的remove");
35         try {
36             list = test.buildList();
37             for (Iterator iterator = list.iterator(); iterator.hasNext();) {
38                 String str = (String) iterator.next();
39                 list.remove(str);
40             }
41         } catch (Exception e) {
42             // java.util.ConcurrentModificationException
43             e.printStackTrace();
44         }
45         
46         System.out.println("-4-使用list的remove(int)方法. [由后向前删除]");
47         list = test.buildList();
48         for (int i = list.size(); i > 0; i--) {
49             list.remove(i - 1);
50         }
51 
52         System.out.println("-5-使用list的remove(int)方法. [由前向后删除]");
53         list = test.buildList();
54         for (int i = 0; i < list.size(); i++) {
55             list.remove(0);
i=i-1
56 } 57 } 58 59 private List<String> buildList() { 60 List<String> list = new ArrayList<String>(); 61 list.add("a"); 62 list.add("b"); 63 list.add("c"); 64 return list; 65 } 66 }

运行输出:

 1 -1-
 2 java.util.ConcurrentModificationException
 3     at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
 4     at java.util.AbstractList$Itr.next(AbstractList.java:420)
 5     at cn.iwoo.ListRemoveTest.main(ListRemoveTest.java:15)
 6 -2-
 7 java.lang.IllegalStateException
 8     at java.util.AbstractList$Itr.remove(AbstractList.java:433)
 9     at cn.iwoo.ListRemoveTest.main(ListRemoveTest.java:29)
10 -3-
11 java.util.ConcurrentModificationException
12     at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
13     at java.util.AbstractList$Itr.next(AbstractList.java:420)
14     at cn.iwoo.ListRemoveTest.main(ListRemoveTest.java:41)
15 -4-
16 -5-

原因:List每remove掉一个元素以后,后面的元素都会向前移动,此时如果执行i=i+1,则刚刚移过来的元素没有被读取。

1,2,3会出现异常.
4,5 正确运行.


网上一般介绍当遇到ConcurrentModificationException时都推荐使用Iterator.remove [也就是第2种方法], 但测试结果说明Iterator.remove也不是很好用.

分析:
问题出在List的remove(Object) 和 remove(int)方法区别上[本例中使用的是ArrayList].

modCount++;

ArrayList的remove(Object)没有修改在ArrayList中用于计数的数值, 所以123代码运行抛出异常. 而 4,5中使用remove(int)方法则可以正确运行.


结论: 使用ArrayList.remove(int) 比较保险...

posted @ 2012-11-13 13:22  zdp072  阅读(415)  评论(0编辑  收藏  举报