当前位置: 首页 > 面试题库 >

Java中的迭代器如何知道何时引发ConcurrentModification异常

拓拔弘亮
2023-03-14
问题内容

我有以下引发ConcurrentModificationException的代码,因为我在同一列表上使用了两个不同的迭代器,其中一个正在修改列表。因此,第二个迭代器在读取列表时会引发异常,因为其他某个迭代器已经修改了列表。

    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


问题答案:

回答此类问题的一种好方法是查看源代码,例如ArrayList的源代码。搜索ConcurrentModificationException

您应该能够说出事情的运作方式是这样的:

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

根据您的情况,通过iterator1对列表执行删除操作会更改列表的结构操作计数(modCount)。当iterator2要求删除它时,它会看到其expectedModCount,最初接收为0,与列表的当前mod计数不同。

应当指出,这it.remove是一种特殊情况。当迭代器自行执行删除操作时,它会进行expectedModCount相应调整,以与基础列表保持同步。



 类似资料:
  • 本文向大家介绍Java 如何绕过迭代器遍历时的数据修改异常,包括了Java 如何绕过迭代器遍历时的数据修改异常的使用技巧和注意事项,需要的朋友参考一下 前言 既然是绕过迭代器遍历时的数据修改异常,那么有必要先看一下是什么样的异常。如果在集合的迭代器遍历时尝试更新集合中的数据,比如像下面这样,我想输出 Hello,World,Java,迭代时却发现多了一个 C++ 元素,如果直接删除掉的话。 那么我

  • 所有订阅操作都使用以下内容: 所有取消订阅操作都使用以下内容: 和通知者:

  • 问题内容: 我已经使用try catch块处理了Jenkins管道步骤。在某些情况下,我想手动引发异常。但它显示以下错误。 我检查了scriptApproval部分,没有待批准的项目。 问题答案: 如果要在异常情况下中止程序,则可以使用管道步骤以错误停止管道执行。范例: 如果要以成功状态停止管道,则可能需要使用某种布尔值来指示必须停止管道,例如:

  • 问题内容: 有没有一种方法(在编码时)知道在执行python代码时期望哪些异常?由于不知道会抛出哪种异常类型(并且不要告诉我阅读文档,所以很多时候我都会捕获90%的基础Exception类)。很多时候,异常可以从深处传播出去。次文档未更新或不正确)。有某种工具可以检查吗?(例如通过阅读python代码和库)? 问题答案: 我猜一个解决方案可能只是不精确,因为缺少静态的输入规则。 我不知道有什么工具

  • 问题内容: 考虑这个简单的程序。该程序有两个文件: 和HelloWorld.java: 正如您在第一堂课中所看到的,我在其中想抛出异常的地方添加了一条注释(“ // throw exception”)。我必须为异常定义自己的类,还是可以在Java中使用一些常规的异常类? 问题答案: 您可以创建自己的Exception类: 在您的代码中:

  • 我试图了解更多关于异步/等待的信息,尤其是编译器如何知道在异步方法和等待时“暂停”,而不产生额外的线程。 例如,假设我有一个异步方法,如 我知道是我的方法被“挂起”并且调用它的线程返回线程池的地方,一旦跟踪连接打开的完成,然后找到一个可用的线程来运行。 这就是我困惑的地方。我查看了OpenAsync的源代码(https://referencesource.microsoft.com/#System