0

Consider the following code.

As you might expect, the deleteFruitByName method throws a ConcurrentModificationException when a fruit is removed inside a for-each loop.

How can i avoid that in such cases?

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

    }
}


0

2 Answers 2

1

To avoid ConcurrentModificationException you need to use Iterator here.

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

From 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.

Update: to iterate collection in class Fluit use this code

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());
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

does doing this removes object from fruites too?
yes, it removes. But your code has a little mistake. With this Fruit.deleteFruitByName("apple"); you remove elements from static collection in class Fluit, but with for loop in main - you iterete other collection, that initialized in main.
0

The following should work (just writing this here so may be a compile error):

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.