java - 从 ArrayLists 中删除对象时如何避免 concurrentModificationException”
问题描述
考虑以下代码。
如您所料,当在 for-each 循环中删除水果时,deleteFruitByName 方法会引发 ConcurrentModificationException。
在这种情况下如何避免这种情况?
import java.util.ArrayList;
public class Stringplay {
public static void main(String[] args) {
ArrayList<Fruit> fruites = new ArrayList<Fruit>();
new Fruit(32, "apple", "red");
new Fruit(64, "orange", "orange");
new Fruit(12, "banana", "red");
new Fruit(42, "grape", "purple");
fruites.addAll(Fruit.fruits);
Fruit.deleteFruitByName("apple");
for (Fruit fruit : fruites) {
System.out.println(fruit.getName());
}
}
}
public class Fruit {
public int weight;
public String name;
public String type;
public static ArrayList<Fruit> fruits = new ArrayList<Fruit>();
public Fruit(int weight, String name, String type) {
this.weight = weight;
this.name = name;
this.type = type;
fruits.add(this);
}
public String getName() {
return name;
}
public static void deleteFruitByName(String fruitName) {
for (Fruit fruit : fruits) {
if (fruit.getName().equals(fruitName)) {
fruits.remove(fruit);
}
}
}
}
解决方案
为避免 ConcurrentModificationException,您需要在此处使用 Iterator。
public static void deleteFruitByName(String fruitName) {
Iterator<Fruit> it = fruits.iterator();
while (it.hasNext()) {
Fruit fruit = it.next();
if (fruit.getName().equals(fruitName)) {
it.remove();
}
}
}
来自 java文档
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法之外的任何方式,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。
更新: 要在 Fluit 类中迭代集合,请使用此代码
public class Main {
public static void main(String[] args) {
new Fruit(32, "apple", "red");
new Fruit(64, "orange", "orange");
new Fruit(12, "banana", "red");
new Fruit(42, "grape", "purple");
Fruit.deleteFruitByName("apple");
for (Fruit fruit : Fruit.fruits) {
System.out.println(fruit.getName());
}
}
}
推荐阅读
- jquery - Is it possible to start -webkit-animation at a paused state before clicking the run button?
- json - 我怎样才能得到这个对象的价值?
- node.js - 降级节点出现错误“无效版本”
- android - 如何允许用户从 Firebase 中删除他们的帖子?
- c# - 如何在 docker 容器中运行 asp.net 核心应用程序?
- gradle - gradle构建成功后,运行spring boot应用程序时找不到类
- mysql - 使用 Pandas 通过 SSH 隧道在 AWS 上查询我的数据库
- android - 为什么我的 Gradle 在我的 Unity Android 版本上失败?
- java - 为什么 Java Stack 有搜索方法?
- c++ - 我如何在 C++ 中使用“stdafx.h”?