如何删除列表中的项目?

How to remove item in List?

我在嵌套for循环中有两个List,当我在内部匹配一个项目时,我想将其删除以提高性能。

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

您无法在迭代 Collection 时从中删除项目,而 Java 中的 foreach 循环本质上就是这样做的。您必须创建一个新的 List<String[]> 并收集您希望删除的所有元素,然后在遍历 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);

它不是那么漂亮,但你可以使用迭代器来完成它:

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<> themeList 的具体类型(数组列表、链表等),这可能比复制变体快,也可能不快。

如果您使用的是 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]))