java - 如何安全地从列表中删除元素
问题描述
for (Iterator<Long> it = ids.iterator(); it.hasNext(); ) {
Long temp = it.next().longValue();
if (oo.contains(temp)) {
it.remove();
}
}
我做对了吗?
如果我在单线程和多线程环境中都使用迭代器remove()
,我不会得到任何ConcurrentModificationException
或其他异常吗?
解决方案
如果我在单线程和多线程环境中都使用迭代器
remove()
,我不会得到任何ConcurrentModificationException
或其他异常吗?
通常,对于单线程和多线程环境,您都会得到ConcurrentModificationException
s.
CME 可能由许多原因引起,而不仅仅是“Iterator.remove
在使用迭代器迭代列表时不使用”。例如,下面是一些生成 CME 的代码:
List<String> list = new ArrayList<>(List.of("1", "2"));
Iterator<String> iter = list.iterator();
iter.next();
list.add(0, "first!"); // adding to the list while iterating over it
iter.remove(); // we're using Iterator.remove here, still CME!
还,
List<String> list = new ArrayList<>(List.of("1", "2"));
// make two iterators of the same list
Iterator<String> iter1 = list.iterator();
Iterator<String> iter2 = list.iterator();
iter1.next(); // advance one of them
iter1.remove(); // we're using Iterator.remove here
iter2.next(); // iter2 doesn't know about iter1 has removed an element, so CME
问题中发生了类似的事情:为什么这个 Java 代码会触发 ConcurrentModificationException?我已经回答了。
不过,在您的代码中,我没有看到这样的事情发生,所以我认为在单个线程中应该没问题。
但是,如果该列表可由多个线程访问,那么您就有问题了。Iterator.remove
不应该为您解决所有多线程同步问题。如果您没有进行适当的同步,那么另一个线程可以在您迭代列表时对列表进行任何结构更改,也就是说。解决此问题的一种方法(根据您的用例肯定有更好的方法)是在对列表进行任何结构更改之前和迭代之前获取锁。
标准库提供了一堆线程安全的集合。如果需要,请选择合适的。
推荐阅读
- angular - Angular中window.location.href的等价物是什么
- c - C:读取文件中的第二行后的 Realloc() 导致垃圾值
- android - 如果文本字段包含“\r”/回车,则单击按钮
- python - 列表的平均值,以 100 项为单位
- python - PYQT:如果选择了组合框中的项目,则设置 lineedit 的文本
- node.js - 删除带有 Cheerio 某些 URL 的链接标签
- gradle - 如何构建 Gradle 构建以允许构建相互依赖的库
- java - 如何将结果从 Java 中的本机查询转换为字符串?
- spring-boot - thymeleaf 模板中未加载静态资源
- angular - Promise 在 Angular 中返回