Java ConcurrentHashMap和For Each Loop

2 java thread-safety

假设我有以下内容ConcurrentHashMap:

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

         indentificationDocuments.put(1, "Passport");
         indentificationDocuments.put(2, "Driver's Licence");
Run Code Online (Sandbox Code Playgroud)

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

NES*_*ove 6

由a生成的迭代器ConcurrentHashMap弱一致的.那是:

  • 他们可以与其他业务同时进行
  • 他们永远不会抛出ConcurrentModificationException
  • 它们可以保证在构造时只存在一次元素,并且可以(但不保证)反映构造后的任何修改.

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

类似地,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, ""));
}
Run Code Online (Sandbox Code Playgroud)

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