Search code examples
listclasscastexceptionconcurrentmodificationcopyonwritearraylist

How to remove item in List?


I have two List in nest for loop, When I matched a item in inner, I want to remove it so that performance will up.

List<String[]> brandList = readCsvFile("/tmp/brand.csv");
List<String[]> themeList = readCsvFile("/tmp/theme.csv");

for (String[] brand : brandList) {
    for (String[] theme : themeList) {
        if (brand[0].equals(theme[0])) {
            themeList.remove(theme);
        }
    }
}

I got a java.util.ConcurrentModificationException error. If I changed to CopyOnWriteArrayList, The error as below:

CopyOnWriteArrayList<String[]> themeList = (CopyOnWriteArrayList<String[]>)readCsvFile("/tmp/theme.csv");

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.concurrent.CopyOnWriteArrayList

Now how can I do? omit remove? or anyway else?

I think this is what I need:

List<String[]> brandList = readCsvFile("/tmp/brand.csv");
List<String[]> themeList = readCsvFile("/tmp/theme.csv");

for (String[] brand : brandList) {
    List<String[]> toRemove = new ArrayList<String[]>();

    for (String[] theme : themeList) {
        if (brand[0].equals(theme[0])) {
            toRemove.add(theme);
        }
    }

    for (String[] theme : toRemove) {
        themeList.removeAll(theme);
    }
}

Solution

  • You can't remove items from a Collection while you are iterating over it, which it was a foreach loop in Java essentially does. You have to create a new List<String[]> and collect all elements you wish to remove, then delete them in bulk after you have iterated through the Collection:

    List<String[]> brandList = readCsvFile("/tmp/brand.csv");
    List<String[]> themeList = readCsvFile("/tmp/theme.csv");
    List<String[]> toRemove = new ArrayList<String[]>();
    
    for (String[] brand : brandList) {
        for (String[] theme : themeList) {
            if (brand[0].equals(theme[0])) {
                toRemove.add(theme);
            }
        }
    }
    themeList.removeAll(theme);