0

我想了解 Java 的迭代器。为什么它们被设计为抛出并发修改异常?在 C++ STL 中,您可以迭代容器并随时修改内容,但为什么不能在 Java 中进行呢?

编辑:更正的问题。被错误地构图。

4

3 回答 3

5

这是一个示例,说明为什么在迭代列表时尝试修改列表时迭代器会抛出。

假设您的迭代器是使用索引实现的,例如ArrayList:假设您的迭代器现在指向位置 3 List。现在你在 position 添加一个元素1。迭代器不知道你做了什么改变,所以它仍然指向位置 3,但是位置 3 现在保存了曾经在位置 2 的元素,因为一切都被向下移动了。所以你的迭代器现在将访问一个元素两次!那很糟。

所以规则是,当您在迭代列表时修改列表时,您必须从迭代器本身这样做,因此迭代器知道如何使其位置与对列表的修改保持同步。如果您在不通过迭代器的情况下修改列表,迭代器会抛出 aConcurrentModificationException而不是默默地被破坏,例如多次访问一个元素。

于 2013-05-16T17:16:19.127 回答
4

您可以在迭代集合时修改它。您只需要使用Iterator.remove()即可。

例如,如果另一个线程在迭代期间修改了集合,则可能会引发ConcurrentModificationException 。这比未定义的行为更可取。

Java 迭代器不是线程化的。可能存在多个线程,并且迭代器可能在这些线程中表现良好。

于 2013-05-16T15:49:42.957 回答
-2

我不会解释为什么它们是这样设计的,而是让你知道这个小秘密:

如果您在迭代期间从列表中删除,您将得到一个并发异常。如果您在迭代期间删除使用迭代器,您可能会因为某些其他原因而获得并发异常。

像这样的东西

for(Iterator<?> iter = list.getIterator(); iter.hasNext(); )
{ 
   MyClass c = iter.getNext();
   if( //i need to remove this instance)
      iter.remove(iter);
}

将调用包装起来synchronized或将变量标记为volatile可能会帮助您避免并发修改,因为这些会同步对对象的访问,从而防止您同时从多个源访问它。

或使用 [COW 列表] ( http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html )

我今天似乎无法掌握如何在 SO 上链接东西....

于 2013-05-16T15:49:15.110 回答