ListIterator使用时的ConcurrentModificationException异常问题

本文探讨了ListIterator在Java中的使用技巧及其潜在的问题。通过具体示例展示了如何利用ListIterator进行元素查找与添加,并讨论了并发修改异常的原因及避免方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写作业时用到了迭代器ListIterator,主要代码如下,使用了

.hasNext()
.next()
.hasPrevious()
.previous()


ListIterator<Worker> it = workerList.listIterator();
		
		int index = 0;
		while(it.hasNext())
		{
			Worker w = it.next() ; 
			if("li4".equals(w.getName()))
			{
//				it.add( new Worker("zhao6",24,3300));
				index = workerList.indexOf(w);
				System.out.println(index);
//				break;
			}
		}
		workerList.add(index, new Worker("zhao6",24,3300));
		System.out.println(workerList.toString());
		
//		ListIterator<Worker> it1 = workerList.listIterator();
		while(it.hasPrevious())
		{
			Worker w = it.previous() ; 
			if("zhang3".equals(w.getName()))
			{
				it.remove();
//				break;
			}
			System.out.println(workerList.toString());
		}


报错Exception in thread "main" java.util.ConcurrentModificationException,检查后发现,是下面这句代码的使用使程序抛出了异常

workerList.add(index, new Worker("zhao6",24,3300));

ListIterator   it  和集合  workList 同时操作一个资源,语句下方还有

while(it.hasPrevious())
即ListIterator   it 未完成对集合的操作,此时就会抛出异常


-----------------------------------------------------------------------------------------------------

注意:使用ListIterator的

.hasNext()
.next()
.hasPrevious()
.previous()


遍历集合时,注意可能因指针不在集合的头或尾而"错过"某些数据

ConcurrentModificationExceptionJava 中的一种运行异常(RuntimeException),属于 Java 集合框架(Java Collections Framework)中的一部分。该异常主要用于检测集合在遍历过程中是否被外部修改,从而避免不确定的遍历行为。 该异常的产生通常与集合的 fail-fast 机制有关。fail-fast 是 Java 集合框架的一种错误检测机制,用于在多线程或单线程环境下检测集合的并发修改。当一个线程在使用迭代器遍历集合,如果另一个线程(或同一线程的其他部分)修改了集合的结构(如添加、删除或替换元素),迭代器会抛出 ConcurrentModificationException 异常以防止遍历结果的不一致性[^3]。 具体来说,ConcurrentModificationException 的触发条件包括: 1. **使用迭代器遍历集合修改集合结构**:在使用 IteratorListIterator 遍历集合的过程中,如果直接通过集合对象(而非迭代器本身)对集合进行 add、remove 等结构性修改操作,则会触发此异常。 2. **多线程环境下的并发修改**:在多线程环境下,一个线程正在遍历集合的同,另一个线程修改了集合的内容,这会触发 ConcurrentModificationException。 3. **频繁修改集合内容**:例如在 Android 开发中,RecycleView 的 Adapter 使用List 数据源如果在数据频繁更新(如频繁调用 add、remove 操作)被迭代,也可能导致该异常的发生[^4]。 该异常的抛出机制依赖于集合内部的 modCount 和 expectedModCount 两个变量。modCount 表示集合被结构性修改的次数,而 expectedModCount 是迭代器初始化记录的 modCount 值。在迭代过程中,如果发现这两个值不一致,则说明集合被并发修改,从而抛出异常[^2]。 ### 避免和处理 ConcurrentModificationException 的策略 1. **使用迭代器自身的修改方法**:在遍历集合,如果需要修改集合内容,应使用 Iterator 提供的 remove 方法,而不是直接调用集合的 remove 方法[^1]。 2. **使用线程安全的集合类**:在多线程环境中,可以使用 java.util.concurrent 包中的集合类(如 CopyOnWriteArrayList、ConcurrentHashMap 等),这些集合类在并发访问不会抛出 ConcurrentModificationException。 3. **同步控制**:通过使用 synchronized 关键字或 Lock 对象对集合的访问进行同步,确保同一间只有一个线程可以修改或遍历集合。 4. **避免在遍历修改集合结构**:可以通过将需要修改的操作延迟到遍历完成后再执行,或者在遍历创建集合的副本进行操作。 ```java // 使用迭代器的 remove 方法安全地删除元素 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (someCondition(item)) { iterator.remove(); // 正确的方式 } } ``` ### 示例代码:使用 CopyOnWriteArrayList 避免异常 ```java import java.util.concurrent.CopyOnWriteArrayList; public class ConcurrentExample { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("A"); list.add("B"); list.add("C"); // 多线程遍历和修改不会抛出 ConcurrentModificationException new Thread(() -> { for (String s : list) { System.out.println(s); if (s.equals("B")) { list.remove("B"); } } }).start(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值