java.util.ConcurrentModificationException ,遍历集合并同时修改集合,并发造成的异常解决办法

本文介绍在Java中遍历集合时并发修改导致的ConcurrentModificationException异常,并提供了解决方案,即避免在遍历过程中直接修改集合。

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

解决办法:移除并发修改的语句

java.util.ConcurrentModificationException
	java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	java.util.ArrayList$Itr.next(ArrayList.java:851)
	cn.banwxf.shoppingmall.service.CartService.getCartInfo(CartService.java:25)
	cn.banwxf.shoppingmall.servlet.CartServlet.doGet(CartServlet.java:35)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

出现这种情况的原因是,当你在遍历集合时,同时对集合的大小做了修改。
例如我是这样的:我想在双重遍历时将已经得到的元素移除集合
for (CartProduct cartProduct : resultCartProductList) {
            // 如果是同一家商店的
            String productId = cartProduct.getProductId();
            String shopName = cartProduct.getShopName();
            ArrayList<CartProduct> shopProductList = new ArrayList<>();
//            for (CartProduct cartProduct2 : resultCartProductList) {
//                if (productId.equals(cartProduct2.getProductId())) {
//                    shopProductList.add(cartProduct2);
////                    resultCartProductList.remove(cartProduct2);
////                    resultCartProductList
//                }
//            }
            for (int i = 0; i < resultCartProductList.size(); i++) {
                CartProduct cartProduct2 = resultCartProductList.get(i);
                if (productId.equals(cartProduct2.getProductId())) {
                    shopProductList.add(cartProduct2);
//                    resultCartProductList.remove(cartProduct2);
                    resultCartProductList.remove(i);
                }
            }
            CartShopPorduct shopPorduct = new CartShopPorduct(shopName,shopProductList,"");
            productlist.add(shopPorduct);
        }



这样肯定是不行的,所以解决办法就是,移除修改集合的代。


<think>我们正在解决遍历List时删除元素导致的ConcurrentModificationException问题。根据引用内容,我们知道这个异常是因为在遍历过程中直接调用List的remove方法导致modCount和expectedModCount不一致。下面给出几种安全删除的方法,引用相关文献说明。根据引用[1]和[4]:在增强for循环(即迭代器遍历)中直接调用List的remove方法会抛出ConcurrentModificationException,因为modCount增加了但迭代器的expectedModCount没有更新。引用[2]和[3]指出:应该使用迭代器自己的remove方法,这样会同时更新expectedModCount,从而避免异常。因此,我们推荐以下方法:1.使用迭代器遍历调用迭代器的remove方法(最佳实践)2.Java8+使用removeIf方法(内部使用迭代器)3.使用普通for循环调整索引(适用于ArrayList等随机访问列表)4.倒序遍历删除(避免索引错乱)5.使用并发集合(如CopyOnWriteArrayList,但注意性能)下面详细说明:</think>### 解决 Java 遍历 List 时删除元素的 `ConcurrentModificationException` 问题 #### 📌 异常原因分析 当使用增强 for 循环或迭代器遍历 List 时直接调用 `list.remove()`,会导致: ```java List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); for (String item : list) { if ("B".equals(item)) { list.remove(item); // ❌ 直接调用集合的 remove() } } ``` **触发异常机制**: 1. List 内部维护 `modCount`(修改计数器) 2. 迭代器维护 `expectedModCount`(预期修改值) 3. 直接调用 `list.remove()` 会使 `modCount++`,但 `expectedModCount` 未更新 4. 迭代器下次操作时检测到 `modCount != expectedModCount` → 抛出异常[^1][^4] --- ### ✅ 安全删除元素的 5 种方案 #### 方案 1:使用迭代器的 `remove()`(最佳实践) ```java Iterator<String> it = list.iterator(); while (it.hasNext()) { String item = it.next(); if ("B".equals(item)) { it.remove(); // ✅ 同步更新 modCount 和 expectedModCount[^2][^4] } } // 结果:list → ["A", "C"] ``` #### 方案 2:Java 8+ 使用 `removeIf()`(最简洁) ```java list.removeIf(item -> "B".equals(item)); // ✅ 内部自动处理迭代器删除 ``` #### 方案 3:普通 for 循环 + 索引回退(适合 ArrayList) ```java for (int i = 0; i < list.size(); i++) { if ("B".equals(list.get(i))) { list.remove(i); i--; // ✅ 删除后索引回退[^3] } } ``` #### 方案 4:倒序遍历删除(避免索引错位) ```java for (int i = list.size() - 1; i >= 0; i--) { if ("B".equals(list.get(i))) { list.remove(i); // ✅ 倒序删除不影响前方索引 } } ``` #### 方案 5:使用并发集合(线程安全场景) ```java List<String> safeList = new CopyOnWriteArrayList<>(list); for (String item : safeList) { if ("B".equals(item)) { safeList.remove(item); // ✅ 允许遍历修改(牺牲写性能) } } ``` --- ### ❌ 绝对禁止的操作 ```java // 错误 1:增强 for 循环中调用集合 remove() for (String item : list) { list.remove(item); // ❌ 必抛 ConcurrentModificationException[^1][^2] } // 错误 2:迭代器遍历中调用集合 remove() Iterator<String> it = list.iterator(); while (it.hasNext()) { String item = it.next(); list.remove(item); // ❌ 破坏 modCount 一致性[^4] } ``` --- ### 关键原则总结 1. **遍历时删除必须通过迭代器自身**:调用 `iterator.remove()` 保持 `modCount` 和 `expectedModCount` 同步[^4] 2. **多线程环境**:优先使用 `CopyOnWriteArrayList` 或 `Collections.synchronizedList()` + 同步块 3. **Java 8+ 首选**:`removeIf()` 兼顾简洁性与安全性 4. **性能考量**: - 小集合:迭代器方案 - 大集合:先收集待删除元素,遍历后批量删除 > 通过正确使用迭代器控制修改操作,可完全避免 `ConcurrentModificationException`,同时保证数据一致性[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值