当我们在当前节点之后添加或删除某些对象时,Iterator
如何抛出 ConcurrentModificationException
异常?Iterator
是否维护对底层集合的副本或引用?
根据契约,您在迭代集合时不允许修改它(除非使用 Iterator.remove()
等方法)。
如果您这样做,集合不会随意失败,而是会很好地跟踪修改次数,并在检测到并发修改时抛出 ConcurrentModificationException
。
要进行删除操作,您可以使用迭代器的remove()方法,如下所示:
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object object = iterator.next();
/* ... */
if (condition) {
iterator.remove();
}
对于添加操作,您可以将简单的Iterator替换为ListIterator,如下所示
ListIterator<Object> iterator = list.listIterator();
iterator.add(new Object());
那个ConcurrentModificationException可能是你的朋友,你应该学会与它共处。然而,为了完整起见:
有一些非Oracle集合不会抛出ConcurrentModificationException。它们更快(因为它们不花时间检查),显然更灵活,但在使用时需要更加小心。
Oracle有四个(至少)“Concurrent”类,它们不会在java.util.concurrent中抛出异常(ConcurrentHashMap、ConcurrentLinkedQueue、ConcurrentSkipListMap和ConcurrentSkipListSet)。它们比其非并发等效类略慢,但它们是线程安全的,并且它们不会阻塞。无论你做什么,它们都不会破坏你的数据,但它们也不会阻止你破坏它。