当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

集合遍历中操作异常解决

发表于: 2014-08-30   作者:dyy_gusi   来源:转载   浏览次数:
摘要: 在集合操作的时候,我们通常会使用foreach增强for循环遍历集合,比如我们想输出集合中的每个元素,我们可以使用for循环遍历。代码如下: ​ ​ ​ ​//初始化一个集合 static List< String > list = new ArrayList< String >(); list.add("1");

在集合操作的时候,我们通常会使用foreach增强for循环遍历集合,比如我们想输出集合中的每个元素,我们可以使用for循环遍历。代码如下:

    ​    ​    ​    ​//初始化一个集合

static List< String > list = new ArrayList< String >();

list.add("1");

list.add("2");

list.add("3");

list.add("4");

    ​    ​    ​    ​//遍历集合

for (String l : list) {

System.out.println(l);

}

 

 

但是当我们在使用增强for循环的时候,如果我们想在循环中删除一个或者多个元素的时候,直接调运集合的remove()方法是不行的,会报异常:java.util.ConcurrentModificationException。

 

for (String l : list) {

if (l.equals("1")) {

list.remove(l);

}

}

 

 

究其原因,是因为我们在使用集合的remove()操作的时候,java底层会去执行一个modCount++操作,修改modCount这个变量的值。同时我们在执行增强for循环的时候,本质上是在使用集合的Iterator,而这个Iterator也会维护这个modCount的变量,此外它还维护一个expectedModCount变量。也就是说集合本身会维护modCount变量,Iterator会维护modCount和exceptionModCount变量。但是每次在Iterator执行操作的时候,都会先检查modCount变量和exceptionModCount的值是否一致,源代码如下:

final void checkForComodification() {

       if (modCount != expectedModCount)

            throw new ConcurrentModificationException();

}

 

在检查modCount和exceptionModCount的值是否还相同,如果不相同,那么就报异常。在上面for循环的操作中,我们使用for循环遍历,但是在循环内部使用集合自己的remove方法,这个方法把modCount的值给修改,接下来再遍历的时候,使用到了Iterator的方法,这时再检查那两个变量的时候,因为只有modCount被改了,所以他们不一致了,自然要抛异常。好了,现在明白为什么报异常以后,就知道怎么避免这个问题了。

 

我们有两个办法可以避免这个异常。

第一,不要使用集合Iterator相关的方法,不涉及到exceptionModCount变量即可,只涉及到modCount变量即可。说具体点就是我们不要使用任何和Iterator相关的东西,也就是说不要使用争强for循环,当然这样就不会执行检查两个变量是否相同了。代码体现如下:

for (int i = 0; i < list.size(); i++) {

if (list.get(i).equals("4")) {

// list.remove(i);

list.remove(list.get(i));//只使用到集合自己的remove方法,不会涉及到exceptionModCount

}

}

 

第二,我们每次操作的时候,不要只修改modCount变量,同时修改exceptionModCount变量,使之永远保持一致即可。也就是说不要使用集合自己remove方法,使用iterator提供的方法。代码体现如下:

 

Iterator< String > itList = list.iterator();

while (itList.hasNext()) {

if (itList.next().equals("1")) {

itList.remove();//使用Iterator的remove方法,这样modCount和exceptionModCount永远是一致的

}

}

 

 

第三,我们还有个一个择中的办法。首先使用iterator的方法得到所有需要被删除的元素,然后在使用集合的removeAll()方法一次性将要删的的元素都删除,在removeAll方法中,我们也不会涉及到检查modCount和exceptionModCount是否一致的问题。

 

这里只列举了List集合的例子,对于Set集合和Map集合是相同的。



集合遍历中操作异常解决

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
首先声明本文不是讨论Linq,在Framwork2.0中也不支持linq操作的,主要是记录一下List集合的使用方法
1 svn locked某个目录-无法进行更新 产生这种情况大多是因为上次svn命令执行失败且被锁定了。如果cl
本章目标 可以使用表达式语言进行集合的输出 集合操作 集合操作在开发中被广泛的采用,在表达式语言
当在静态初始化块中出现了异常的时候,JVM会抛出 java.lang.ExceptionInInitializerError异常。如果
一.Java中的异常机制继承体系图如下: 二.JAVA异常可分为3种:   (1)编译时异常:java.lang.Excep
当在静态初始化块中出现了异常的时候,JVM会抛出 java.lang.ExceptionInInitializerError异常。如果
Why:ThreadPool没有内建机制标记当前线程在什么时候完成,也没有机制在操作完成时获得返回值,因而
前言   在数据库连接池分析的代码实例中,看到其中使用Enumeration来遍历Vector集合。后来就找了
web.xml 的配置文件 <!-- 配置Spring解决懒加载问题的过滤器 --> <filter> <filter-
今天使用 AsyncHttpClient 开源库,遇到个很崩溃的问题: 方法 setEnableRedirects(false); 从名称
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号