在迭代期间从 ArrayList 中删除多个项目

Remove multiple items from ArrayList during iterator

在使用迭代器遍历 ArrayList 时从 ArrayList 中删除多个项目是否安全?

Iterator<String> iterator = nameList.iterator();
 while(iterator.hasNext()){
     String s = iterator.next();
     List<String> list = work(s);
     for (String s1 : list) {
        nameList.remove(s1);   
    }
}

work() 方法返回在 while 循环运行期间应从 nameList 中删除的名称列表。

不行,不安全,可以扔ConcurrentModificationException。可以在一个临时的List中收集所有要移除的元素,然后在while循环后调用list.removeAll(tmpList)执行移除。

Iterator<String> iterator = nameList.iterator();
List<String> removed = new ArrayList<>();
while(iterator.hasNext()){
    String s = iterator.next();
    removed.addAll(work(s));
}
list.removeAll(removed);

我意识到这可能会降低效率,因为您可能在 String 上调用 work(s) 应该早些从 List 中删除。这可以通过将 tempList 更改为 Set 来改进,并且只为不在 Set 中的 String 调用 work(s)

Iterator<String> iterator = nameList.iterator();
Set<String> removed = new HashSet<>();
while(iterator.hasNext()){
    String s = iterator.next();
    if (!removed.contains(s)) {
        removed.addAll(work(s));
    }
}
list.removeAll(removed);

正如之前的回答所说,从迭代列表中删除一个项目是不安全的。这是抛出 ConcurrentModificationException:

的代码
List<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String s = iterator.next();
    list.remove("1");
}

如果您使用故障安全的 ListIterator,则可以实现您的逻辑。下面是一个基本示例:

Set<String> removed = new HashSet<>();
    ArrayList<String> nameList = new ArrayList<String>();

            ListIterator<String> iterator = nameList.listIterator();
             while(iterator.hasNext()){
                 String s = iterator.next();
                 if (!removed.contains(s)) {
        removed.addAll(work(s));
    }

            }


 nameList.removeAll(removed);
                 System.out.println(nameList);

按照您的逻辑,您必须考虑性能。如果性能不是一个因素,您可以继续并通过 ListIterator 从列表中 add/remove。