在使用Iterator来迭代遍历List的时候如果修改该List对象,则会报java.util.ConcurrentModificationException异常,下面看一个例子演示:

 package com.others;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; public class ArrayListTest { public static void main(String[] args) {
List<String> list = new ArrayList<String>();
//CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
String str = (String) iterator.next();
if(str.equals("c")){
list.remove(str);
}else{
System.out.println(str);
}
}
} }

  结果为:

a
b
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at com.others.ArrayListTest.main(ArrayListTest.java:20)

  当调用list的iterator()方法的时候,返回的是一个Itr对象(实现了Iterator接口):

 public Iterator<E> iterator() {
return new Itr();
}

  我们看一下Itr这个类:

 private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount; //刚创建迭代对象的时候List的modCount public boolean hasNext() {
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification(); //每调用一次next()函数都会调用checkForComodification方法判断一次
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//此方法用来判断创建迭代对象的时候List的modCount与现在List的modCount是否一样,不一样的话就报ConcurrentModificationException异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

  List对象有一个成员变量modCount,它代表该List对象被修改的次数,每对List对象修改一次,modCount都会加1.

  Itr类里有一个成员变量expectedModCount,它的值为创建Itr对象的时候List的modCount值。用此变量来检验在迭代过程中List对象是否被修改了,如果被修改了则抛出java.util.ConcurrentModificationException异常。在每次调用Itr对象的next()方法的时候都会调用checkForComodification()方法进行一次检验,checkForComodification()方法中做的工作就是比较expectedModCount 和modCount的值是否相等,如果不相等,就认为还有其他对象正在对当前的List进行操作,那个就会抛出ConcurrentModificationException异常。

  我们再来分析一下上面那个例子,当例子程序执行到22行的时候,将list对象里面的“c"删除了,同时list对象的modCount值加1,但是Itr对象的expectedModCount没有变,他们肯定是不相等了。等再一次执行next()方法的时候调用了checkForComodification()方法,这时候就抛出异常了。

  我们再将上面那个例子稍微改动一下:将21行改为if(str.equals("d")){,即删除”d"这个元素。运行结果如下:

a

b

c

  这时却没有报异常了,但是“e"却没有输出来,这是为什么呢?原因很简单,我们看到Itr的hashNext()方法:

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

  它是通过Itr的对象的cursor与List对象的size值来判断是否还有未迭代的对象,当遍历完“d"的时候cursor=4,删除”d"的时候,List对象的size就会减1,size首先为5,后来变为4,这时候cursor和size是相等的,hasNext()方法返回的是false,就认为遍历结束了,所以删除以后没有进去执行next()方法了,就没有抛出异常了,当然"e"也没有输出来。

  为了避免这种异常,我们可以使用CopyOnWriteArrayList来代替ArrayList,CopyOnWriteArrayList支持并发访问,所以同时进行迭代和修改是没有问题的。

最新文章

  1. NLog在Asp.Net MVC的实战应用
  2. float4与half4数据类型
  3. centos7 cannot find a valid baseurl for repo base (转载)
  4. ORA-00060:等待资源时检测到死锁的一种处理方法
  5. Eclipse代码提示功能是不是利用反射
  6. HttpRequest类
  7. Esper系列(一)初探
  8. 关于MySQL的分区(partion)
  9. 查询sql 语句的好坏
  10. poj 1411 Calling Extraterrestrial Intelligence Again
  11. mac系统下给文件夹加密方法
  12. CentOS上javaweb开发环境搭建
  13. 使用rsync在windows(服务端)与linux(客户端)之间同步
  14. 【Python3爬虫】拉勾网爬虫
  15. 【PHP】最详细PHP从入门到精通(一)——想学习PHP的朋友们福利来了!
  16. Zookeeper环境搭建
  17. 菜刀(代码执行)函数和命令执行函数详解及Getshell方法
  18. php 对象教程
  19. RTSP 与 RTMP 协议 (转)
  20. ASP.NET Web API 框架研究 Controller创建 HttpController介绍

热门文章

  1. HDU 4888 Redraw Beautiful Drawings 网络流 建图
  2. SharePoint SPUtility.SendEmail 发送邮件设置级别
  3. 《“胡”说IC——菜鸟工程师完美进阶》
  4. serializeArray()与 serialize()
  5. @ZooKeeper注册中心安装(单节点)
  6. 浅谈提升C#正则表达式效率
  7. Gas Station leetcode java
  8. 魅族推送 简介 集成 MD
  9. C# 6.0 的那些事
  10. python对json的操作总结 zz