Java:在ConcurrentHashMap中,为什么在更改密钥时会有不同的输出

时间:2018-03-19 07:51:19

标签: java collections concurrenthashmap

第一次迭代: -

class ConcurrentHashMapBehaviour
{       
    public static void main(String[] args) 
    {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
        map.put("ONE", 1);
        map.put("TWO", 2);
        map.put("THREE", 3);
        map.put("FOUR", 4);
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()){
            String key = (String) it.next();
            System.out.println(key+" : "+map.get(key));
            map.put("SEVEN", 7);
        }
    }
}

输出为:

ONE : 1
FOUR : 4
TWO : 2
THREE : 3
SEVEN : 7

更改密钥后的第二次迭代

class ConcurrentHashMapBehaviour
{       
    public static void main(String[] args) 
    {
        ConcurrentHashMap<String, Integer> map = new 
        ConcurrentHashMap<String, Integer>();

        map.put("ONE", 1);
        map.put("TWO", 2);
        map.put("THREE", 3);
        map.put("FOUR", 4);
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()){
            String key = (String) it.next();
            System.out.println(key+" : "+map.get(key));
            map.put("FIVE", 5);
        }           
    }
} 

输出为:

ONE : 1
FOUR : 4
TWO : 2
THREE : 3

所以我的问题是为什么第一次迭代包括SEVEN作为输出而不是第二次迭代中的FIVE?

2 个答案:

答案 0 :(得分:6)

Javadoc(我强调):

  

类似地,Iterators,Spliterators和Enumerations在创建迭代器/枚举 时或之后的某个时刻返回反映哈希表 状态的元素。

换句话说,迭代器可用的视图没有任何保证。在创建Iterator之后,它可能会或可能不会知道对地图的更改。唯一的保证是

  

他们不会抛出ConcurrentModificationException。

答案 1 :(得分:0)

键入

Iterator<String> it = map.keySet().iterator();
while (it.hasNext())
{
    String key = it.next();
    System.out.println(key + " : " + map.get(key));
    map.put("FIVE", 5);
}

每次打印值时,您都可以将("FIVE", 5)放到地图上,但这并不会将其添加到正在运行的迭代器中。迭代器不会更新。实际上,在没有迭代器的情况下更改迭代列表或映射(例如,使用for each循环)将导致ConcurrentModificationException

在第一次循环后执行第二次循环并创建新的迭代器。它还会打印出新值:

Iterator<String> it2 = map.keySet().iterator();
while (it2.hasNext())
{
    String key = it2.next();
    System.out.println(key + " : " + map.get(key));
}

输出:

FIVE : 5
ONE : 1
FOUR : 4
TWO : 2
THREE : 3