2010-11-13 75 views
1

我有一个列表ListIterator<PointF>作为类字段。我填写方法grow()。当我尝试从这个列表中使用迭代器时,我得到ConcurrentModificationExceptionJava:无法更改迭代器列表

ListIterator<ListIterator<PointF>> i = mPoints.listIterator(); 
while (i.hasNext()) { 
    ListIterator<PointF> j = i.next(); 
    if (j.hasNext()) 
     PointF tmp = j.next(); // Exception here 
} 

我不知道为什么会发生这种代码会导致exeption以任何方法除了grow()

+0

请发布一个简短但完整的程序来演示问题。 – 2010-11-13 13:23:04

+0

@Jon Skeet问题解决了,我在获得迭代器后修改了我的列表'mPoints'。 – Heheid 2010-11-13 13:42:26

回答

4

如果底层列表的变化,会抛出ConcurrentModificationException之前获得的迭代器。所以不要在实例字段中存储迭代器。

0

我们可以肯定地说,ConcurrentModificationException意味着在调用获取迭代器后的某个时刻,基础迭代器已被修改。

这并不总是意味着像多线程中的并发;通过在循环中迭代列表并删除元素,可以很容易地触发此异常。所以,如果没有其他线程可能修改这个,那么我们可以说当前线程已经修改了迭代器的底层数据结构。

这里没有足够的代码可以肯定,但是您存储迭代器的做法有点可疑。您何时将(内部)迭代器添加到mPoints?如果它们引用的集合随时在迭代器创建后发生变化,它将在调用时抛出此异常。因此,只要将迭代器添加到mPoints集合中,就可以有效地锁定迭代器的数据结构以进行更改,但代码根本不会很清楚。

所以我怀疑这是你的问题的根本原因。除非是短期的(通常在单个词法范围内,例如单个方法调用),否则出于您看到的原因,存储迭代器可能是个坏主意。这可能是更好的存储底层集合自己的参考,然后创建上面的代码块中的迭代器,像这样:

ListIterator<Iterable<PointF>> i = mPoints.listIterator(); 
while (i.hasNext()) { 
    Iterator<PointF> j = i.next().iterator(); 
    if (j.hasNext()) 
     PointF tmp = j.next(); 
} 

然后再精确的解决方案取决于你的方法的总体架构。要记住的主要事项是不要长期存储迭代器,因为几乎不可能使其可靠工作。即使它现在可以正常工作,它也会在代码的不同部分之间创建一种不可见的依赖关系,而这些依赖关系几乎总是会被实施什么应该是微不足道的改变的人所打破。