Search code examples
javahashmapiterator

java.util.ConcurrentModificationException, but I'm iterating over a copy, not the collection I'm modifying


Please read the description of my problem before marking duplicate.

private void cleanTrash() {

    HashMap<String, OutfitInfo> tempOutfits = outfits;
    Iterator iter = tempOutfits.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry mapElement = (Map.Entry) iter.next();
        String key = (String) mapElement.getKey();
        OutfitInfo info = (OutfitInfo) mapElement.getValue();
        if (info.getParentID().equals(trashID)) {
            outfits.remove(key);
        }
    }
    HashMap<String, ItemInfo> tempItems = items;
    iter = tempItems.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry mapElement = (Map.Entry) iter.next();
        String key = (String) mapElement.getKey();
        ItemInfo info = (ItemInfo) mapElement.getValue();
        if (info.getParentID().equals(trashID)) {
            items.remove(key);
        }
    }

}

In the above code I am getting the concurrent modification exception. I understand that this error means that I can't modify a collection while I'm iterating over it. HOWEVER, I made a copy of the collection before assigning the iterator, and the collection being modified is not the one that's being iterated over. So why am I still getting this message, and how do I fix it?


Solution

  • HashMap<String, OutfitInfo> tempOutfits = outfits; does not create a copy. Both varaibles tempOutfits and outfits point to the same instance.

    If you actually want to copy you can do:

     HashMap<String, OutfitInfo> tempOutfits = new HashMap<>(outfits);
    

    This line creates a new HashMap and initializes it with the content of outfits


    As you already have the Iterator, instead of removing the entry directly from the collection. Call iterator.remove(); to remove the item the iterator currently references. No need to copy the collection.

    So:

    private void cleanTrash() {
        Iterator iter = outfits.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry mapElement = (Map.Entry) iter.next();
            String key = (String) mapElement.getKey();
            OutfitInfo info = (OutfitInfo) mapElement.getValue();
            if (info.getParentID().equals(trashID)) {
                iter.remove();
            }
        }
        iter = items.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry mapElement = (Map.Entry) iter.next();
            String key = (String) mapElement.getKey();
            ItemInfo info = (ItemInfo) mapElement.getValue();
            if (info.getParentID().equals(trashID)) {
                iter.remove();
            }
        }
    }