解决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].
ArrayList的remove(Object)没有修改在ArrayList中用于计数的数值, 所以123代码运行抛出异常. 而 4,5中使用remove(int)方法则可以正确运行.
结论: 使用ArrayList.remove(int) 比较保险...