ConcurrentModificationException thrown on for each in android

Viewed 330

i passing list of tags in forloop for iterate but its raised ConcurrentModificationException

 public void clearTag() {
    List<Tag> tags = binding.search.tagView.getTags();
    Log.d(TAG, "clearTags: " + tags);
    for (Tag tag : tags) {
        Log.d(TAG, "clearTag: " + tag + " " + tag.getLayoutColor());
        if (tag.getLayoutColor() == R.color.red) {
           tags.remove(tag);
        } else if (tag.getLayoutColor() == R.color.blue) {
            tags.remove(tag);
        } else if (tag.getLayoutColor() == R.color.green) {
            tags.remove(tag);
        }
    }
    updateTagVisibility();
    //resetFilter();
}
3 Answers

This is because remove and add operations are not allowed while iterating through an array. So you need to store all elements to remove in different array, then remove them at once. Here is an example:

public void clearTag() {
    List<Tag> tags = binding.search.tagView.getTags();
    List<Tag> tagsToRemove = new ArrayList<>();
    Log.d(TAG, "clearTags: " + tags);
    for (Tag tag : tags) {
        Log.d(TAG, "clearTag: " + tag + " " + tag.getLayoutColor());
        if (tag.getLayoutColor() == R.color.red) {
           tagsToRemove.add(tag);
        } else if (tag.getLayoutColor() == R.color.blue) {
            tagsToRemove.add(tag);
        } else if (tag.getLayoutColor() == R.color.green) {
            tagsToRemove.add(tag);
        }
    }
    tags.removeAll(tagsToRemove);
    updateTagVisibility();
    //resetFilter();
}

If you change your for each loop to a 'normal' for loop, like with (int = 0; i < size; i++), it possibly works. Make sure everytime you delete an element you have to go one element back i--;

I recently encountered this exception. It occurs when you try to modify a collection you are already using/iterating.

Your for each loop picks one Tag object from the tags List and inside the loop you are removing the object from the same list. This is not allowed in Java.

You can alter your code like this :

public void clearTag(){
    List<Tag> tags = binding.search.tagView.getTags();
    // Create a dummy arrayList to store the tags to remove
    List<Tag> removedTags = new ArrayList<Tag>();
    Log.d(TAG, "clearTags: " + tags);
    for (Tag tag : tags) {
        Log.d(TAG, "clearTag: " + tag + " " + tag.getLayoutColor());
        if (tag.getLayoutColor() == R.color.red) {
           removedTags.add(tag);
        } else if (tag.getLayoutColor() == R.color.blue) {
            removedTags.add(tag);
        } else if (tag.getLayoutColor() == R.color.green) {
            removedTags.add(tag);
        }
    }

    // remove the tags
    tags.removeAll(removedTags)
    updateTagVisibility();
    //resetFilter();
}

Reference

Related