繁体   English   中英

从 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 文档

此类的 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());
        }
    }
}

以下应该工作(只是在这里写,所以可能是一个编译错误):

public static void deleteFruitByName(StringfruitName) {fruit.removeIf(fruit =>fruit.getName().equals(fruitName)); }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM