我想知道Java的迭代器。为什么它们被设计为抛出并发修改异常?在C ++ STL中,您可以遍历容器并随意修改内容,但为什么不能在Java中执行此操作?
编辑:更正了问题。框架不正确。
答案 0 :(得分:5)
以下是为什么迭代器在您迭代时尝试修改列表时会抛出的示例。
假设您的迭代器是使用索引实现的,就像在ArrayList
中一样:假设您的迭代器现在指向List
中的位置3。现在,您在位置1
添加元素。迭代器不知道你做了什么改变,所以它仍然指向位置3,但是位置3现在保持了曾经位于第2位的元素,因为一切都向下移动了。所以你的迭代器现在将访问一个元素两次!那很糟糕。
所以规则是当你在迭代它时修改一个列表时,你必须从迭代器本身这样做,所以迭代器知道如何保持它的位置与列表的修改同步。如果在不经过迭代器的情况下修改列表,则迭代器会抛出ConcurrentModificationException
而不是静默地损坏,例如不止一次地访问元素。
答案 1 :(得分:3)
您可以在迭代时修改集合。您只需使用Iterator.remove()。
例如,如果另一个线程在迭代期间修改了集合,则可能抛出ConcurrentModificationException。这比未定义的行为更可取。
Java迭代器没有线程化。可能存在多个线程,并且迭代器在这些中可能表现良好。
答案 2 :(得分:-1)
我不会解释他们为什么按照他们的方式设计,而是让你了解这个小秘密:
如果在迭代期间从列表中删除,则会出现并发异常。 如果在迭代期间使用迭代器删除,则可能由于其他原因而获得并发异常。
像这样的东西
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上链接内容....