Java ConcurrentHashMap和For Each Loop

时间:2015-07-07 17:17:18

标签: java thread-safety

假设我有以下ConcurrentHashMap

ConcurrentHashMap<Integer,String> indentificationDocuments = new ConcurrentHashMap<Integer,String>();

         indentificationDocuments.put(1, "Passport");
         indentificationDocuments.put(2, "Driver's Licence");

如何使用for循环迭代地图并将每个条目的值附加到字符串?

2 个答案:

答案 0 :(得分:5)

ConcurrentHashMap生成的迭代器为weakly consistent。那就是:

  
      
  • 他们可以与其他行动同时进行
  •   
  • 他们永远不会抛出ConcurrentModificationException
  •   
  • 他们可以保证在施工时只存在一次元素,并且可能(但不保证)反映施工后的任何修改。
  •   

最后一个要点非常重要,迭代器在创建迭代器后的某个时刻返回地图视图,引用javadocs for ConcurrentHashMap的不同部分:

  

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

因此,当您循环访问如下所示的键集时,需要仔细检查该项目是否仍存在于集合中:

for(Integer i: indentificationDocuments.keySet()){
    // Below line could be a problem, get(i) may not exist anymore but may still be in view of the iterator
    // someStringBuilder.append(indentificationDocuments.get(i));
    // Next line would work
    someStringBuilder.append(identificationDocuments.getOrDefault(i, ""));
}

将所有字符串附加到StringBuilder本身的行为是安全的,只要您在一个线程上执行它或完全以线程安全的方式封装StringBuilder

答案 1 :(得分:0)

我不知道如果你真的在问这个问题,而是迭代任何你迭代keySet()

的地图
StringBuffer result = new StringBuffer("");

for(Integer i: indentificationDocuments.keySet()){
        result.append(indentificationDocuments.get(i));
}

return result.toString();