码迷,mamicode.com
首页 > 其他好文 > 详细

解决ArrayList的ConcurrentModificationException

时间:2015-10-14 23:22:49      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:

问题 :在list<String> 中清空所有的记录,只使用使用单循环,不使用removeAll()

 

可以写出五种方式,代码如下:

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

 3运行结果如下:

Xml代码  技术分享
  1. -1-使用jdk5.0以后的增强for循环去remove  
  2. java.util.ConcurrentModificationException  
  3. -2-使用Iterator的remove  
  4. -3-iterator遍历+list的remove  
  5.     at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)  
  6.     at java.util.ArrayList$Itr.next(ArrayList.java:753)  
  7.     at com.jdk.ListRemoveTest.main(ListRemoveTest.java:14)  
  8. java.util.ConcurrentModificationException  
  9.     at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)  
  10.     at java.util.ArrayList$Itr.next(ArrayList.java:753)  
  11.     at com.jdk.ListRemoveTest.main(ListRemoveTest.java:39)  
  12. -4-使用list的remove(int)方法. [由后向前删除]  
  13. -5-使用list的remove(int)方法. [由前向后删除]  

2,4,5运行正常,1,3抛出

java.util.ConcurrentModificationException

 

4问题原因:

1,3都是因为list的长度改变,Iterator执行next()方法时,调用checkForComodification()时出错,1,3是同一个问题,这两个方法remove操作都是执行的是ArrayList中的remove方法,根本原因在于expectedModCount与modCount他们的不相等,由于执行了ArrayList中的remove(),modCount在每一次循环值会发生改变,而expectedModCount并没有发生,在执行checkForComodification()方法就会抛出异常。

2之所以正确运行是因为调用了Iterator的remove方法,4,5不会执行checkForComodification()操作,所以不会出现这种异常。

 

5结论 :在执行remove()不要将ArrayList 与Interator混合使用,单独使用Interator以及ArrayList的删除都是OK的技术分享

6参考的源码

Iterator的next()方法:

Java代码  技术分享
  1. public E next() {  
  2.     checkForComodification();  
  3.     int i = cursor;  
  4.     if (i >= size)  
  5.         throw new NoSuchElementException();  
  6.     Object[] elementData = ArrayList.this.elementData;  
  7.     if (i >= elementData.length)  
  8.         throw new ConcurrentModificationException();  
  9.     cursor = i + 1;  
  10.     return (E) elementData[lastRet = i];  
  11. }  
  12.   
  13. final void checkForComodification() {  
  14.     if (modCount != expectedModCount)  
  15.         throw new ConcurrentModificationException();  
  16. }  

 Iterator的remove()方法:

Java代码  技术分享
  1. public void remove() {  
  2.     if (lastRet < 0)  
  3.         throw new IllegalStateException();  
  4.     checkForComodification();  
  5.   
  6.     try {  
  7.         ArrayList.this.remove(lastRet);  
  8.         cursor = lastRet;  
  9.         lastRet = -1;  
  10.         //当执行remove操作后,将改变的modCount值重新赋给expectedModCount  
  11.              expectedModCount = modCount;  
  12.     } catch (IndexOutOfBoundsException ex) {  
  13.         throw new ConcurrentModificationException();  
  14.     }  
  15. }  

 ArrayList的remove()方法:

 

 

Java代码  技术分享
  1. /** 
  2.    * Removes the first occurrence of the specified element from this list, 
  3.    * if it is present.  If the list does not contain the element, it is 
  4.    * unchanged.  More formally, removes the element with the lowest index 
  5.    * <tt>i</tt> such that 
  6.    * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt> 
  7.    * (if such an element exists).  Returns <tt>true</tt> if this list 
  8.    * contained the specified element (or equivalently, if this list 
  9.    * changed as a result of the call). 
  10.    * 
  11.    * @param o element to be removed from this list, if present 
  12.    * @return <tt>true</tt> if this list contained the specified element 
  13.    */  
  14. ublic boolean remove(Object o) {  
  15.       if (o == null) {  
  16.           for (int index = 0; index < size; index++)  
  17.               if (elementData[index] == null) {  
  18.                   fastRemove(index);  
  19.                   return true;  
  20.               }  
  21.       } else {  
  22.           for (int index = 0; index < size; index++)  
  23.               if (o.equals(elementData[index])) {  
  24.                   fastRemove(index);  
  25.                   return true;  
  26.               }  
  27.       }  
  28.       return false;  
  29.   }  
  30.   
  31.   /* 
  32.    * Private remove method that skips bounds checking and does not 
  33.    * return the value removed. 
  34.    */  
  35.   private void fastRemove(int index) {  
  36.       //此处modCount发生了改变,但expectedModCount仍然未发生变化,所以再执行下一次循环时执行  
  37.       //Interator的next()方法当然会报错  
  38.       modCount++;  
  39.       int numMoved = size - index - 1;  
  40.       if (numMoved > 0)  
  41.           System.arraycopy(elementData, index+1, elementData, index,  
  42.                            numMoved);  
  43.       elementData[--size] = null; // Let gc do its work  
  44.   }  

解决ArrayList的ConcurrentModificationException

标签:

原文地址:http://www.cnblogs.com/helinzi/p/4881032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!