从 ArrayLists 中删除对象时如何避免 concurrentModificationException”
how to avoid concurrentModificationException when removing an object from to ArrayLists"
考虑以下代码。
如您所料,当在 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 doc
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
更新:
在 class 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());
}
}
}
下面应该可以工作(只是写在这里所以可能是一个编译错误):
public static void deleteFruitByName(String fruitName) {
fruits.removeIf(fruit => fruit.getName().equals(fruitName));
}
考虑以下代码。
如您所料,当在 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 doc
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
更新: 在 class 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());
}
}
}
下面应该可以工作(只是写在这里所以可能是一个编译错误):
public static void deleteFruitByName(String fruitName) { fruits.removeIf(fruit => fruit.getName().equals(fruitName)); }