`
dyy_gusi
  • 浏览: 209610 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

集合遍历中操作异常解决

    博客分类:
  • Java
阅读更多

在集合操作的时候,我们通常会使用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集合是相同的。



3
0
分享到:
评论

相关推荐

    java集合类遍历的同时如何进行删除操作.docx

    在Java编程中,集合类遍历的同时进行删除操作是一个常见的需求,但如果不正确地执行,可能会导致`ConcurrentModificationException`。这个问题主要出现在迭代器正在遍历集合时,集合本身被修改的情况。以下是对这个...

    Iterator遍历过程中list删除导致异常

    然而,当我们尝试在使用`Iterator`遍历集合的过程中直接修改集合时,可能会遇到`ConcurrentModificationException`异常。这个异常通常发生在多线程环境下对共享数据进行并发修改,但即使在单线程情况下,如果在迭代...

    iterator 遍历循环代码

    通过上述分析可以看出,`&lt;s:iterator&gt;`标签是Struts2框架中非常实用的一个功能,它简化了集合遍历的过程,使得开发者可以更加专注于业务逻辑的实现。同时,我们也需要注意到在实际项目中可能遇到的一些问题,并采取...

    C#数组遍历

    - 避免越界:在遍历过程中确保索引不会超出数组长度,否则会导致`IndexOutOfRangeException`异常。 - 修改数组:在foreach循环中,如果尝试修改数组元素,可能会导致编译错误,因为foreach循环不支持在迭代过程中...

    超级技能遍历源码

    遍历是一种基本的编程技术,常用于访问树、图或其他集合中的每个元素。这种技术广泛应用于各种编程语言,如Java、C++、Python等。 遍历的目的通常是为了执行特定操作(如搜索、排序、更新或统计)或者理解数据结构...

    java 中遍历取值异常(Hashtable Enumerator)解决办法

    为了解决这个问题,我们需要确保每次循环只调用一次 `next()` 方法,并将返回的键存储在一个局部变量中,然后使用这个变量进行操作。修正后的代码如下: ```java // 使用迭代器遍历 Iterator&lt;String&gt; it = ...

    十六进制遍历

    遍历是一种程序设计的基本操作,用于访问或处理集合中的每个元素,无论是数组、列表、字符串还是其他结构。对于十六进制遍历,这通常涉及到从最低有效位到最高有效位逐个处理每一位,或者按照特定步长(例如每四位一...

    遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置

    在Java编程中,`ConcurrentModificationException`是一个常见的运行时异常,通常发生在多线程环境下对集合进行迭代和修改操作时。此问题的核心在于,Java的集合类(如ArrayList、LinkedList、HashSet等)并不支持...

    java 异常、IO、集合

    集合框架还提供了`Iterator`和`Stream`接口,用于遍历和操作集合。`Iterator`是传统迭代方式,`Stream`是Java 8引入的新特性,支持函数式编程风格,如过滤、映射和聚合操作。 总的来说,理解并熟练掌握Java的异常...

    JAVA基础测试中常见的异常问题汇总-Java-CSDN

    本文将深入探讨在JAVA基础测试中常见的异常问题,帮助开发者更好地理解和解决这些问题。 1. **运行时异常**:Java中的运行时异常(RuntimeException)是程序设计错误引起的,如空指针异常(NullPointerException)...

    06-1: Python课程 教程 进阶 实战 集合:基础操作、内存分配、数据运算、固定集合

    - 集合的遍历:通过for循环可以逐个遍历集合中的元素,但遍历顺序是不确定的,因为集合是无序的。 4. 固定集合(frozenset): - 定义:frozenset是集合的一个不可变版本,一旦创建就不能修改。它可以作为字典的...

    collection集合体系与并发修改异常的解决方法

    Collection 集合体系提供了多种方式来存储和操作数据,但在多线程环境下,需要注意并发修改异常的出现原因和解决方法,以免程序出现错误。 Collection 集合体系的知识点总结: * Collection 集合体系的顶层接口是 ...

    dotnet C# 多线程集合的 Linq 获取值同时写入集合将会抛出异常.rar

    4. **避免在迭代过程中修改集合**:如果可能,尽量避免在遍历集合时对其进行修改,这包括在Linq查询中。 5. **使用`AsEnumerable()`或`AsQueryable()`**:这些方法可以创建一个只读的视图,但请注意,这并不能解决...

    完美解决python遍历删除字典里值为空的元素报错问题

    - 当尝试在遍历字典的过程中直接修改字典时(如删除元素),Python解释器为了保持数据结构的一致性,会抛出 `RuntimeError` 异常。 - 原因在于字典迭代器会在遍历过程中调用 `next` 方法,而直接删除字典元素会改变...

    EL语言遍历集合出现PropertyNotFoundException 的两种情况

    2. **异常处理**:在JSP中使用条件标签(如`&lt;c:if&gt;`)或在Java代码中进行异常处理,避免访问不存在的属性或空集合。 3. **EL表达式优化**:使用EL的`empty`操作符检查变量或集合是否为空,如`${not empty user....

    JAVA 集合操作

    在Java编程中,集合操作是不可或缺的一部分,它们用于存储、管理以及操作对象。这篇博文将深入探讨Java集合框架,包括其基本概念、常见类、接口和实现方式,以及如何进行有效的集合操作。以下是对这些知识点的详细...

    C#遍历文件夹获取指定后缀名文件

    递归遍历是指当目录中包含子目录时,程序将进入子目录内部,再次执行遍历操作。这个过程会一直持续到所有的子目录都被遍历完成。递归遍历是处理含有子目录的文件夹的自然和有效方式。 知识点5:使用List集合存储...

    Java 常见问题解决集合.docx

    **解决:** 当在遍历集合的同时对其进行修改时,会引发这个异常。可以通过以下方式解决: - **使用线程安全集合:** 使用线程安全的集合,如`ConcurrentHashMap`。 - **安全修改集合:** 在遍历时如果需要修改集合,...

    JAVA程序设计-3期(KC005) KC 005 050000 003-教学单元设计-单元三 数据与异常处理程序设计.doc

    4. **Iterator接口**:学习如何遍历集合中的元素。 5. **泛型**:了解泛型的基本概念和使用,以提高代码的类型安全性和重用性。 6. **List接口与实现类**:熟练运用ArrayList和LinkedList,理解它们之间的性能差异。...

    HashMap和List遍历方法及如何遍历删除元素总结

    原因在于,在增强for循环中,实际上是使用Iterator来遍历List,而Iterator并不能检测到List的变化,从而导致异常。 解决方法 要解决List遍历删除元素的问题,可以使用Iterator来遍历List,并使用Iterator的remove...

Global site tag (gtag.js) - Google Analytics