java修改集合抛出ConcurrentModificationException异常

测试代码为:

public static void main(String[] args) {
		List<String> strList = new ArrayList<String>();
		strList.add("1");
		strList.add("2");
		strList.add("3");
		strList.add("4");
		for(String str:strList){
			if(str.equals("4")){
				strList.remove(str);
			}
		}
	}

运行后结果如下:

跟踪代码,抛出异常的地方具体在:

public E next() {
            checkForComodification();
	    try {
		E next = get(cursor);
		lastRet = cursor++;
		return next;
	    } catch (IndexOutOfBoundsException e) {
		checkForComodification();
		throw new NoSuchElementException();
	    }
	}

遍历时返回一个元素之前,会调用checkForComodification()函数进行检查,该函数实现为:

final void checkForComodification() {
	    if (modCount != expectedModCount)
		throw new ConcurrentModificationException();
	}

modCount 为ArrayList修改的次数,expectedModCount 为期望修改的次数,在删除第四个元素之前,modCount 和expectedModCount 均为4,而调用ArrayList的remove()方法后,modCount 变为5,但expectedModCount 仍为4,因此出现上述异常。

解决方法为:使用 Iterator的remove()方法取代ArrayList的remove()方法,可以避免ConcurrentModificationException异常。

巧合的是,如果要删除的元素正好是集合中倒数第二个元素,则不会抛出此异常。Iterator遍历获取一个元素之前会先调用hasNext()方法来判断是否还有元素,该方法实现为:

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

其中cursor为遍历的位置,从0开始,在上面的next()方法中更新。

删除元素"3"后,cursor的值为3,而size()也返回3,hasNext()返回false,就不会调用next()方法了,因此也不存在ConcurrentModificationException异常。

删除元素"4"后,cursor的值变为4,而size()返回3,hasNext()返回true,调用next()方法时就会抛出ConcurrentModificationException异常。

附上一篇资料:

Java ConcurrentModificationException异常原因和解决方法:http://www.cnblogs.com/dolphin0520/p/3933551.html

时间: 2024-08-26 10:53:23

java修改集合抛出ConcurrentModificationException异常的相关文章

捕获Java线程池执行任务抛出的异常

Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常, public interface Runnable { public abstract void run();} 那么如果 run() 方法中抛出了RuntimeException,将会怎么处理了? 通常java.lang.Thread对象运行设置一个默认的异常处理方法: java.lang.Thread.setDefaultUncaughtExceptionHandler(UncaughtExce

java 检查抛出的异常是否是要捕获的检查性异常或运行时异常或错误

/** * Return whether the given throwable is a checked exception: * that is, neither a RuntimeException nor an Error. * @param ex the throwable to check * @return whether the throwable is a checked exception * @see java.lang.Exception * @see java.lang

有时候在操作Session时,系统会抛出如下异常:java.lang.IllegalStateException: Cannot create a session after the response has been committed

有时候在操作Session时,系统会抛出如下异常 java.lang.IllegalStateException: Cannot create a session after the response has been committed 原因1: Session 的创建语句: HttpSession seesion = request.getSession(); 之前有Response的输出语句. 应该把HttpSession seesion = request.getSession(); 放

hadoop学习;hdfs操作;运行抛出权限异常: Permission denied;api查看源码方法;源码不停的向里循环;抽象类通过debug查找源码

eclipse快捷键alt+shift+m将选中的代码封装成方法:alt+shift+l将选中的代码添加对应类型放回参数 当调用一个陌生方法时,进入源码不停的向里循环,当找不到return类似方法的时候,可以看到最原始的方法 package com.kane.hdfs; import java.io.InputStream; import java.net.URL; import org.apache.hadoop.fs.FsUrlStreamHandlerFactory; import org

迭代器使用过程中为什么抛出ConcurrentModificationException

出现的场景:在迭代器对集合进行遍历的同时,集合本身进行变更操作(add(), remove(), set()). 当正常调用时: import java.util.ArrayList; import java.util.Iterator; public class TestDemo { public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<>(); a.add(1); a.add(

druid抛出的异常------javax.management.InstanceAlreadyExistsException引发的一系列探索

最近项目中有个定时任务的需求,定时检查mysql数据与etcd数据的一致性,具体实现细节就不说了,今天要说的就是实现过程中遇到了druid抛出的异常,以及解决的过程 异常 异常详细信息 五月 05, 2017 4:16:00 下午 com.alibaba.druid.proxy.DruidDriver warn 警告: register druid-driver mbean error javax.management.InstanceAlreadyExistsException: com.al

try ,finally都抛出异常如何处理.如果try中抛出了异常,在控制权转移到调用栈上一层代码之前, finally 语句块也会执行,如果finally抛出异常,try语句快抛出的那个异常就

package com.github.jdk7; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * try ,finally都抛出异常如何处理.如果try中抛出了异常,在控制权转移到调用栈上一层代码之前, * finally 语句块也会执行,如果finally抛出异常,try语句快抛出的那个异常就丢失了. * * @author doctor * * @since 2014年

解决httpclient抛出URISyntaxException异常

这两天在使用httpclient发送http请求的时候,发现url中一旦包含某些特殊字符就会报错.抛出URISyntaxException异常,比如struts漏洞的利用url:(大括号就不行) redirect:${%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23webroot%3d%23req.getSession().getServletContext().getReal

finally中使用return会吃掉catch中抛出的异常

今天学习大神的文章:深入理解java异常处理机制 学到一个有意思的知识点.如果在finally中使用return会吃掉catch中抛出的异常. 看例子: [java] view plaincopy public class TestException { public TestException() { } boolean testEx() throws Exception { boolean ret = true; try { ret = testEx1(); } catch (Excepti