【问题标题】:How does the iterator simultaneously read and delete elements from a collection?迭代器如何同时从集合中读取和删除元素?
【发布时间】:2019-01-19 10:32:34
【问题描述】:

我创建了以下代码。 我的目标是在读取集合时检查使用迭代器删除元素。 谁能解释为什么在将哈希图的值集合添加到链表并为该列表创建迭代器后会引发 concurrentModificationException,但在将集合添加到列表后获取迭代器时不会引发相同的问题?

我知道原因很简单,我想要一些容易获得的东西,但我只是想确认我的想法是否正确。

还有 2 点。 1. 由于 hashmap 不是线程安全的,为什么我们不能在迭代器读取时向其中添加任何元素? 2. 如果是,那么我们如何从地图中移除元素?

 package com.Users;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

    public class Temp{
        public static void main(String arg[]){
            HashMap<String, String> map=new HashMap();
            map.put("A", "B");
            map.put("C", "D");

            LinkedList<String> list=new LinkedList<>();

            //****** concurent exception is thrown when ever line 1 is swapped with line 2 ******
            Iterator<String> iterator=list.iterator();  //line no. 1
            list.addAll(map.values());    //line no. 2
            //******************

            while(iterator.hasNext()){
                if(iterator.next().equals("B")){
                    iterator.remove();
                }
            }


            System.out.println(list);
        }
    }

【问题讨论】:

    标签: collections linked-list hashmap thread-safety concurrenthashmap


    【解决方案1】:

    HashMap 上的迭代器本质上是 fail-fast,这本质上意味着它们会尽快中止操作,立即暴露故障。

    集合维护一个名为modCount 的内部计数器。每当从集合中添加或删除项目时,都会修改此计数器。

    迭代时,每次调用 next() 时,都会将 modCount 的当前值与初始值进行比较。如果不匹配,它会抛出 ConcurrentModificationException 从而中止整个操作。


    1. 由于 hashmap 不是线程安全的,所以为什么我们不能在迭代器读取时向它添加任何元素?

    我们无法在迭代时修改集合,因为大多数集合(例如 ArrayList、HashMap)默认具有快速失败的迭代器。


    1. 如果是,那么我们如何从地图中删除元素?

    我们能够删除您示例中的元素,因为我们在 iterator.remove() 中使用了迭代器的 remove() 方法。 如果我们使用集合的remove() 方法,这也会抛出ConcurrentModificationException

    请阅读this了解详细说明。

    【讨论】:

    • 有道理!!谢谢你的解释。
    猜你喜欢
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    相关资源
    最近更新 更多