-2

我有下列抛出ConcurrentModificationException的代码,因为我在同一个列表上使用两个不同的迭代器,其中一个正在修改列表。所以,第二个迭代器在读取列表时抛出异常,因为其他迭代器已经修改了列表。Java中的Iterator如何知道何时抛出ConcurrentModification异常

List<Integer> list = new ArrayList<>(); 

    populate(list);//A method that adds integers to list 

    ListIterator<Integer> iterator1 = list.listIterator(); 
    ListIterator<Integer> iterator2 = list.listIterator(); 

    while (iterator1.hasNext()) { 
     if(iterator1.next() < 5) 
      iterator1.remove(); 
    } 

    while (iterator2.hasNext()){ 
     if(iterator2.next() < 5) { 
     //Call handler 
     } 
    } 

我的问题是如何iterator2知道内部list已经被一些其他修改迭代器如果还没有达到这一点还没有被去除iterator1的元素?它是如何发现其他一些iterator突变了list?一种方法可以跟踪大小,但这不能成为其他迭代器可以替换任何元素的原因。

+0

你为什么在意?您在修改列表之前创建了迭代器。有可能是一个“脏”的国旗,但是,又一次,你为什么要这样的代码工作? – stdunbar

+1

我不希望像这样的代码工作。但我很在乎,知道如何检测到这种情况。 –

+0

使用Source是免费的! –

回答

3

回答这样的问题的一个好方法是查看源代码,例如the source code for ArrayList。搜索ConcurrentModificationException

你应该能够告诉大家,事情的工作,而像这样:

  • 集合对象有修改计数,开始在每当添加或删除或类似的操作出现零个增加。
  • 当创建迭代器对象时,我们将集合的当前修改计数存储在迭代器中。
  • 每次使用迭代器时,它都会根据迭代器创建时得到的mod计数来检查集合的mod计数。如果这些值不同,则引发异常。

在你的情况下,列表上进行通过iterator1删除操作来更改列表的结构操作数(modCount)。当要求删除iterator2时,它会将其初始接收为0的expectedModCount与当前列表的mod计数不同。

应该注意it.remove是一个特例。当迭代器自己删除时,其expectedModCount会相应地进行调整,以与基础列表保持同步。

+0

得到了方法。谢谢! –

+0

不客气。源代码在这里非常有用,变量的名称和注释非常酷。顺便说一句,我在回答中增加了一点 - 我认为有人(正确)低估了,因为我忽略了关于迭代器本身执行删除操作的技术问题。它没有改变基本的想法,但在这里完成是件好事。 –