`
仁生之狼
  • 浏览: 42802 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Arraylist使用remove(Object)方法 抛出的异常java.util.ConcurrentModificationException

    博客分类:
  • java
阅读更多
工作中碰到个ConcurrentModificationException。代码如下:
List list = ...;
for(Iterator iter = list.iterator(); iter.hasNext();) {
    Object obj = iter.next();
    ...
    if(***) {
        list.remove(obj);
    }
}

在执行了remove方法之后,再去执行循环,iter.next()的时候,报java.util.ConcurrentModificationException(当然,如果remove的是最后一条,就不会再去执行next()操作了)

下面来看一下源码
public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}

public interface Collection<E> extends Iterable<E> {
    ...
    Iterator<E> iterator();
    boolean add(E o);
    boolean remove(Object o);
    ...
}
这里有两个remove方法

接下来来看看AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {  
//AbstractCollection和List都继承了Collection
    protected transient int modCount = 0;
    private class Itr implements Iterator<E> {  //内部类Itr
        int cursor = 0;
        int lastRet = -1;
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();  //特别注意这个方法
            try {
                E next = get(cursor);
                lastRet = cursor++;
                return next;
            } catch(IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);  //执行remove对象的操作
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;  //重新设置了expectedModCount的值,避免了ConcurrentModificationException的产生
            } catch(IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)  //当expectedModCount和modCount不相等时,就抛出ConcurrentModificationException
                throw new ConcurrentModificationException();
        }
    }    
}


remove(Object o)在ArrayList中实现如下:
public boolean remove(Object o) {
    if (o == null) {
            for (int index = 0; index < size; index++)
        if (elementData[index] == null) {
            fastRemove(index);
            return true;
        }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
private void fastRemove(int index) {
    modCount++;  //只增加了modCount
    ....
}

所以,产生ConcurrentModificationException的原因就是:
执行remove(Object o)方法之后,modCount和expectedModCount不相等了。然后当代码执行到next()方法时,判断了checkForComodification(),发现两个数值不等,就抛出了该Exception。
要避免这个Exception,就应该使用remove()方法。
这里我们就不看add(Object o)方法了,也是同样的原因,但没有对应的add()方法。一般嘛,就另建一个List了


下面是网上的其他解释,更能从本质上解释原因:
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
分享到:
评论

相关推荐

    Java.util包.docx

    java.util.ArrayList 类提供了可调整大小的数组,并实现了List接口。以下是关于ArrayList中的要点: • 它实现了所有可选的列表操作,并且还允许所有元素,包括空值null。 • 它提供了一些方法来操作内部用来存储...

    Java Methods-java.util.ArrayList.ppt

    Java Methods-java.util.ArrayList.ppt

    java.util包介绍.pdf

    java.util包介绍.pdf很详细的!!!!

    java.util 包 是Java中很大的一个集合

    运用下列类进行JAVA编程: Date Calendar Random 使用 Collection 接口及其实现类 ArrayList LinkedList 使用 HashMap 使用Vector 等方法的使用

    Java学生成绩管理系统源代码

    Java学生成绩管理系统源...import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer;

    JAVA SCM供应链项目代码

    import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import ...

    Java学生成绩管理系统实例(ArrayList)

    import java.util.ArrayList; import java.util.Iterator; import java.util.Scanner; /** * @Author Ziph * @date 2020/2/19 * @Email mylifes1110@163.com */ public class TestDemo implemen

    Java中ArrayList的removeAll方法详解

    主要给大家介绍了关于Java中ArrayList的removeAll方法的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来看看吧。

    xml2jsonjar包

    import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import ...

    项目源码-java企业QQ项目

    【项目源码】-java企业QQ项目 ... import java.awt....import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.JOptionPane; import com.mingrisoft.userList.User;

    Java遍历arrayList的四种方法

    import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ArrayListDemo { public static void main(String args[]){ List&lt;String&gt; list = new ArrayList(); list.add(...

    Java调用百度人脸对比接口进行人脸(图片)对比

    前三步和人脸检测代码一样 ...import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class FaceMatch{ /** * 重要提示代码中所需工具类 * FileUtil,Ba

    数据库工具类DatabaseUtil.java

    * 返回记录总数, 使用方法: getAllCount("SELECT count(ID) from tableName") 2004-06-09 * 可滚动的 Statement 不能执行 SELECT MAX(ID) 之类的查询语句(SQLServer 2000) * * @param sql * 需要执行的 SQL *...

    项目源码-java图书馆管理系统

    import java.util.ArrayList; import java.util.List; import com.wsy.model.Back; import com.wsy.model.BookInfo; import com.wsy.model.BookType; import com.wsy.model.Borrow; import com.wsy.model.Operater;...

    Java设计二次元动漫人物演出活动小游戏代码.docx

    import java.util.ArrayList; import java.util.Random; import java.util.Scanner; public class AnimeShowGame { // 声明全局变量 private static ArrayList&lt;String&gt; characters = new ArrayList(); private ...

    Java集合多线程安全.docx

    import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * @author: Raicho * @Description: * @program: mianshi * @create: 2020-07-17 15:32 **/ public class ...

    Java课程设计-老鼠走迷宫

    import java.util.ArrayList; import java.util.Random; import java.util.Scanner; /** * 使用递归分割绘制迷宫 * * @author WangSong * * @Time 2020-6-22 */ abstract class Arithmetic { /** 路表示为1...

    CacheManager.java 管理缓存

    import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; /** * 文件名:CacheManager.java 管理缓存 * 版本信息:V1.0 * 日期:2013-06-18 * Copyright BDVCD Corporation 2013 *...

    java 同一用户不能同时登陆问题

    import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpSession; import javax.servlet....

    公司质量控制部门管理活动的 Java 代码.docx

    import java.util.ArrayList; import java.util.List; public class QualityControlDepartment { // 定义变量 private String departmentName; private List&lt;String&gt; managementActivities; // 构造函数 ...

Global site tag (gtag.js) - Google Analytics