0

我在嵌套循环中有两个列表,当我在内部匹配一个项目时,我想删除它以便提高性能。

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

我有一个java.util.ConcurrentModificationException错误。如果我改为 CopyOnWriteArrayList,错误如下:

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

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

现在我该怎么办?省略删除?还是别的?

我认为这是我需要的:

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

3 回答 3

3

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);
于 2016-02-13T13:39:03.803 回答
0

它不是那么漂亮,但你可以使用迭代器来做到这一点:

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

for (String[] brand : brandList) {
    Iterator<String[]> themeIterator = themeList.iterator();
    while (themeIterator.hasNext()) {
        String[] theme = themeIterator.next();
        if (brand[0].equals(theme[0])) {
            themeIterator.remove();
            // If you are sure there is only one theme per brand, add a break here
            // break;
        }
    }
}

根据List<> themeListis 的具体类型(数组列表、链表等),这可能会或可能不会比复制变体更快。

于 2016-02-13T14:26:18.130 回答
0

如果您使用的是 Java 8 功能,则可能会使用类似这样的功能,并且可能会更快:

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

// Extract unique values of the first column from the brand list
// into a structure suited for fast lookup
Set<String> names = brandList.stream()
        .map(columns -> columns[0])
        .collect(Collectors.toSet())

// Remove all entries from themeList where the value of the
// first column exists in names
themeList.removeIf(columns -> names.contains(columns[0]))
于 2016-02-17T23:57:05.577 回答