为什么迭代器不会抛出并发修改异常?

时间:2016-01-30 10:10:36

标签: java hashmap concurrentmodification

为什么这个方法不会抛出并发修改? if if(next.equals(" 3")它没有。但是,我将它改为等于(" 1")它确实。这里发生了什么?

    private void checkConcurrentModification(){

        Map<String, Integer> map = new HashMap<>();

        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);


        Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();

        while(iterator.hasNext()){
            String next = iterator.next().getKey();
            map.put(next, 1);
            if(next.equals("3")){ //does not throw exception
 //if(next.equals("1")){ //throws exception
                map.put("4", 4);
            }
        }

        for(Entry<String, Integer> entry : map.entrySet()){
            System.out.println("entry key and value" +entry.getKey() + " : " +entry.getValue());
        }

    }


prints:
entry key and value1 : 1
entry key and value2 : 1
entry key and value3 : 1
entry key and value4 : 4

3 个答案:

答案 0 :(得分:2)

这取决于HashMap

的实施

如果你在Java 7下运行它,那么使用if (next.equals("3"))它会抛出ConcurrentModificationException,而1则会抛出3

如果你在Java 8下运行它,那么使用1它将不会抛出异常,而3则会抛出异常。

原因是当您在Java 7下迭代地图时,第一个键将是1,最后一个键是1。所以你在修改值的同时还有其他值要迭代。

在Java 8下,迭代中的第一个键是3,最后一个键是next()

如果您在遇到最后一个密钥时修改了地图,它将不会检查该修改,因为它只会在您下次尝试呼叫hasNext()时检查它,但在最后一个值之后{{1返回false,因此不会调用next()并避免异常。

答案 1 :(得分:2)

在您在循环中更改地图后尝试访问ConcurrentModificationException之前,不会抛出iterator.next().getKey();。在示例中,"3"是原始映射中的最后一个键,并且在抛出异常之前退出循环。对于原始地图中除最后一个之外的每个键,都会抛出异常。

答案 2 :(得分:1)

如果在上一步中向地图添加了新键,则迭代器到达下一个地图键时会抛出

ConcurrentModificationException。因此,如果您测试的密钥不是地图中的最后一个密钥,则只会获得异常。在你的情况下,3肯定是最后一个。

注意:由于HashMap没有订单,因此在一台计算机上3可能是最后一次,在其他12上可能是。