`
编程足球
  • 浏览: 256956 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

List 遍历 ConcurrentModificationException

    博客分类:
  • java
 
阅读更多
有如下代码片段:
public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
        // 依次输出结果
		for (Integer integer : list) {
			System.out.println(integer);
		}
	}


但是如果在遍历的过程中有remove()方法,则会报错
for (Integer integer : list) {
	System.out.println(integer);
	if(integer.intValue() == 2){
	     list.remove(integer);
	}
}


Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
	at java.util.AbstractList$Itr.next(Unknown Source)
	at study.lgf.study.Foreach.main(Foreach.java:23)


其实在使用foreach的时候系统采用如下方式解析:
for (Iterator<Integer> iter = list.iterator(); iter.hasNext();) {
	Integer integer = iter.next();
	System.out.println(integer);
	if(integer.intValue() == 2){
		list.remove(integer);
	}
}




关于Iterator的源码
    private class Itr implements Iterator<E> {
    	
    	// 当前指针位子
    	int cursor = 0;

    	// iter.next(); 对应的值的位置
    	int lastRet = -1;

    	// list.iterator() 时候List修改的次数
    	int expectedModCount = modCount;

    	// 通过判断size和cursor来判断是否还有数据
    	public boolean hasNext() {
                return cursor != size();
    	}

    	/**
    	 * 1. 判断是否被修改过,如果被修改过则直接报错
    	 * 2. 获得当前下标对应的值
    	 * 3. lastRet = cursor++; 保存当前位置,并且指向下一个
    	 * 4. 返回获得的值
    	 */
    	public E next() {
                checkForComodification();
    	    try {
    		E next = get(cursor);
    		lastRet = cursor++;
    		return next;
    	    } catch(IndexOutOfBoundsException e) {
    		checkForComodification();
    		throw new NoSuchElementException();
    	    }
    	}

    	/**
    	 * 1. 直接移除当前位置的对象
    	 * 2. 指针往后倒一位lastRet < cursor
    	 * 3. lastRet = -1; 当前位置已删除,如果再次移除则直接报错
    	 * 4. expectedModCount = modCount;  同步修改次数
    	 */
    	public void remove() {
    	    if (lastRet == -1)
    		throw new IllegalStateException();
                checkForComodification();

    	    try {
    		AbstractList.this.remove(lastRet);
    		if (lastRet < cursor)
    		    cursor--;
    		lastRet = -1;
    		expectedModCount = modCount;
    	    } catch(IndexOutOfBoundsException e) {
    		throw new ConcurrentModificationException();
    	    }
    	}

    	/**
    	 * 如果在遍历过程中发生变化,则直接报错
    	 */
    	final void checkForComodification() {
    	    if (modCount != expectedModCount)
    		throw new ConcurrentModificationException();
    	}
    }



由此可以知道
java.util.ConcurrentModificationException
的报错原因是应为List在编译过程中修改了,不管是remove,add还是其他什么操作


正确的解决方案就是通过内置的删除方法
/**
 * 通过iterator来遍历,可以正常删除
 * 但是在遍历过程中不能对list进行编辑操作,否则会报错
 */
for (Iterator<Integer> iter = list.iterator(); iter.hasNext();) {
	Integer integer = iter.next();
	System.out.println(integer);
	if(integer.intValue() == 2){
		iter.remove();
	}
}


/**
 * 通过普通的for循环,在移除时候i--(remove时候所有数据向前移动一位)
 * 而且如果在遍历过程中使用add(i),也可以正常遍历到.
 * 但是如果list.add(index, element)则很容易出错 看index和i的关系
 * 如果i>index则可能导致重复遍历一次,i<index....
 */
for (int i = 0; i < list.size(); i++) {
	Integer integer = list.get(i);
	System.out.println(integer);
	if(integer.intValue() == 3){
		list.remove(integer);
		i--;
	}
}

// 建议使用第一种,编译时候锁定list,不在对其进行编辑操作
分享到:
评论

相关推荐

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

    HashMap和List遍历方法及如何遍历删除元素总结 HashMap和List都是Java中最常用的数据结构,它们都可以用来存储和操作数据。然而,在遍历和删除元素时,需要小心地处理,以免出现问题。下面总结了HashMap和List的...

    java中List对象集合的遍历方法(三个)

    如果在遍历过程中需要移除元素,必须使用`it.remove()`,直接调用`list.remove()`会导致并发修改异常(ConcurrentModificationException)。 ### 第二种:增强型for循环(foreach) ```java for (A a : list) { /...

    java.util.ConcurrentModificationException 异常问题详解1

    ConcurrentModificationException 异常是 Java 中一个常见的异常,它发生在 Iterator 遍历集合时,集合同时被修改引起的异常。在 Java 中,集合类如 ArrayList、LinkedList 等都可能会抛出这个异常。 在了解这个...

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

    在Java编程中,`Iterator`是用于遍历集合(如`List`, `Set`等)的重要工具。然而,当我们尝试在使用`Iterator`遍历集合的过程中直接修改集合时,可能会遇到`ConcurrentModificationException`异常。这个异常通常发生...

    Java list利用遍历进行删除操作3种方法解析

    这个示例中,会抛出 ConcurrentModificationException 异常,因为在遍历 list 时,不能修改 list 的内容。为了解决这个问题,可以使用 CopyOnWriteArrayList,避免这种异常: ```java CopyOnWriteArrayList&lt;String&gt;...

    Java中List集合的遍历实例详解

    此外,foreach循环不能在遍历过程中修改集合,否则会抛出`ConcurrentModificationException`异常。 3. **索引遍历** 最传统的方式是通过索引来遍历List集合,这种方式适用于需要访问元素索引的情况: ```java ...

    java-遍历map

    - 在遍历`Map`时,如果在遍历过程中尝试修改`Map`(例如添加或删除元素),可能会引发`ConcurrentModificationException`异常。因此,在遍历的同时不要修改`Map`。 - 使用流API遍历时,虽然代码更简洁,但性能上可能...

    【Java面试题】List如何一边遍历,一边删除?

    在Java编程中,遍历并删除List集合是一个常见的操作,但在实际编程中,如果不使用正确的方法,可能会导致`java.util.ConcurrentModificationException`异常。本文主要针对这个面试题,详细讲解如何在遍历List的同时...

    java中循环遍历删除List和Set集合中元素的方法(推荐)

    在Java编程中,遍历并删除集合(如List或Set)中的元素是一项常见的操作,但如果不正确地执行,可能会导致`ConcurrentModificationException`异常。这个异常通常在尝试修改正在迭代的集合时出现,因为Java的集合迭代...

    如何遍历一个java集合

    在面试中,除了基本的遍历方式,还可能考察一些高级话题,如并发遍历(ConcurrentModificationException)、性能优化(如避免在循环中调用`size()`方法)以及如何处理null元素等。同时,理解不同集合类的底层实现和...

    正确遍历删除List中的元素方法(推荐)

    在Java编程中,遍历并删除List中的元素是一项常见的操作,但如果不小心处理,可能会遇到错误,如`ConcurrentModificationException`。以下是几种常见的遍历删除List元素的方法及其注意事项: 1. **通过增强的for...

    Java如何在List或Map遍历过程中删除元素

    使用For-each循环遍历List时,不能直接在循环体中调用`remove()`方法,因为这会导致`ConcurrentModificationException`。这是因为For-each循环内部使用的是迭代器,而迭代器不支持在遍历过程中直接修改集合。示例...

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

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

    java的list取之方法

    当多个线程同时对`List`进行修改时,可能会抛出`ConcurrentModificationException`异常。为了解决这个问题,可以使用`CopyOnWriteArrayList`或者手动同步代码块。 ### 总结 本篇介绍的是Java中List的基本操作以及...

    Java ArrayList遍历修改代码实例解析

    然而,在遍历 ArrayList 时,如果需要删除某些元素,可能会遇到 ConcurrentModificationException 异常。今天,我们将讨论如何正确地遍历和修改 ArrayList。 遍历 ArrayList 的正确方法 在遍历 ArrayList 时,不能...

    Java 实例 - List 循环移动元素源代码+详细指导教程.zip

    迭代器是Java集合框架提供的一种统一的遍历方式,它可以安全地删除元素,而不会抛出ConcurrentModificationException。以下是一个使用迭代器移动元素的例子: ```java List&lt;String&gt; list = new ArrayList(); // ...

    【IT十八掌徐培成】Java基础第10天-04.List-迭代器-对象等价性.zip

    4. **迭代器与List的关系**:在处理List时,迭代器是首选的遍历方式,因为它提供了一种安全的、避免并发修改异常(ConcurrentModificationException)的方式。当在一个线程中使用迭代器遍历List,而在另一个线程中...

    java中List的用法.pdf

    - **迭代器(Iterator)**:`Iterator`是Java集合框架的一部分,它提供了一种安全的方式来遍历集合,可以方便地进行添加、删除操作,且不会抛出`ConcurrentModificationException`。示例代码中的`it.hasNext()`和`...

    在list集合中输入元素,去除重复的元素并输出

    根据给定文件的信息,本文将详细介绍如何在Java的List集合中去除重复元素的三种方法:使用for循环、使用迭代器以及利用HashSet的特性。 ### 一、使用for循环去除重复元素 这种方法的基本思想是通过双重循环来遍历...

    Java List简介_动力节点Java学院整理

    List 提供了一个名为 `ListIterator` 的迭代器子接口,它可以更灵活地遍历 List。ListIterator 支持向前和向后遍历,以及在迭代过程中添加、修改和删除元素,而普通的 Iterator 只能进行基本的判断、取出和删除操作...

Global site tag (gtag.js) - Google Analytics