问题一:对于ArrayList,使用foreach,一边遍历,一边删除/添加,会报异常。
List<String> list = new ArrayList<String>();
list.add("aaa1123");
list.add("aaabbb");
list.add("aaa11ddd23");
list.add("aaa1123dddd");
for(String str : list){
if(str.contains("b")){
list.remove(str);
//list.add("xxx");
}
}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at com.icss.test.Test.main(Test.java:61)
解决方法如下:
方案一:使用迭代器,一边遍历,一边删除。
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String s = iterator.next();
if(s.contains("b")){
terator.remove();
}
}
方案二:使用CopyOnWriteArrayList,使用foreach,一边遍历,一边删除/添加。
CopyOnWriteArrayList<String> listCopy = new CopyOnWriteArrayList<String>();
listCopy.addAll(list);
for(String str : listCopy){
if(str.contains("b")){
listCopy.remove(str);
//listCopy.add(“xxx”);
}
}
方案三:使用另一个集合将要删除的集合项保存下来,最后调用removeAll。
List<String> listTemp = new ArrayList<String>();
for(String str : list){
if(str.contains("b")){
listTemp.add(str);
}
}
list.removeAll(listTemp);
方案四:对ArryList进行for循环删除
for(int i = list.size() - 1; i >= 0; i--){
String s = list.get(i);
if(s.contains("1")){
list.remove(s);
}
}
引起异常的原因如下:
ArrayList结构改变包括:向ArrayList添加、删除元素,或者明确的手动修改数组大小。如果仅仅是给一个元素赋值,不属于结构的改变。
而当ArrayList的结构改变则引起以下问题:
可能导致Iterator报ConcurrentModificationException异常。
注意:当ArrayList使用了iterator()方法产生自身对应的Iterator后,只能使用Iterator自身的remove和add方法来修改ArrayList的结构,其它的修改都会引起ConcurrentModificationException异常,如ArrayList.add(E e)、ArrayList.remove(int index)等。
ArrayList使用AbstractList.modCount(初始的默认值为0)作为结构改变的标示。在ArrayList中,凡是会引起ArrayList结构变化的方法,都会修改modCount(modCount++),以区别是否修改了ArrayList的结构。
如果是对ArrayList的Iterator做修改,在Iterator中会重置expectedModCount=modCount,这样就可以保证在生成Iterator后,只能由Iterator来修改对应的ArrayList的结构。如果此时,ArrayList修改了自身的结构,那么expectedModCoun==modCount将会返回false,从而Iterator会抛出ConcurrentModificationException异常。