Как избежать concurrentModificationException при удалении объекта из ArrayLists " - PullRequest
0 голосов
/ 22 марта 2020

Рассмотрим следующий код.

Как и следовало ожидать, метод deleteFruitByName генерирует исключение ConcurrentModificationException, когда фрукт удаляется внутри для каждого l oop.

Как мне избежать этого в таких случаях?

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);
            }
        }

    }
}


Ответы [ 2 ]

1 голос
/ 22 марта 2020

Чтобы избежать ConcurrentModificationException, вам нужно использовать итератор здесь.

    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 do c

Итераторы, возвращаемые этим Методы класса iterator и listIterator работают без сбоев: если список структурно изменяется в любое время после создания итератора, любым способом, кроме использования собственных методов удаления или добавления итератора, итератор создает исключение ConcurrentModificationException. Таким образом, перед одновременной модификацией итератор быстро и чисто не работает, вместо того, чтобы рисковать произвольным, недетерминированным поведением c в неопределенное время в будущем.

Обновление: для итерации коллекции в классе 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());
        }
    }
}
0 голосов
/ 22 марта 2020

Следующее должно работать (просто написать это здесь, поэтому может быть ошибка компиляции):

publi c stati c void deleteFruitByName (String fruitName) {fruits.removeIf (fruit => fruit). . GetName () равно (fruitName)); }

...