【发布时间】:2018-10-26 14:01:15
【问题描述】:
【问题讨论】:
-
将代码、输出和/或可能的错误消息显示为问题中格式正确的文本,而不是图像或外部链接。
标签: java collections iterator concurrenthashmap
【问题讨论】:
标签: java collections iterator concurrenthashmap
ConcurrentHashMap.iterator() 不保证您在迭代时会看到或不会看到添加的条目。它有一个内部顺序传递条目,如果您在该点之前添加,则取决于您将看不到条目。
如果您再次遍历这些值,您应该会在第二个中看到它在第一个条目之前。
【讨论】:
您使用ConsurrentHashMap 而不是像HashMap 这样的常规Map 实现可能是有原因的。如果您尝试使用其中一种实现并运行您的代码,您会注意到ConcurrentModificationException,每当您在迭代它时更新HashMap 时都会抛出它。如果您将该实现更改为ConcurrentHashMap,这将更改以下内容:
支持检索的完全并发和更新的高预期并发的哈希表。 [...] 检索操作(包括 get)通常不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在开始时保持的结果。
因此,在您迭代 Map 时允许并发更新。现在,您是否可以实际看到该值的问题可能与 Map 实现的迭代顺序有关(它可以在 Java 版本之间更改,因为 通常 在Map)。如果元素是在当前迭代之前插入的,它将不会被迭代。如果元素是在之后插入的,它会在控制台上打印出来。毕竟,你不应该依赖它。
但是,如果您再次遍历 Map
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
System.out.println(map.get(it.next()));
}
您将正确地看到输出中的值:
iPhone
HTC one
S5
Xperia Z <<< here it is
iPhone
HTC one
S5
现在可以证明之前的假设是正确的,因为密钥“Sony”已经被首先迭代,所以它不会出现在之前的迭代中。如果您将此与第一次尝试进行比较,则键“d”已被最后一次迭代,因此它显示在控制台上。确切地说,如果您有一个被迭代的值而不是第一个值,它将显示出来(因为您已经在第二次迭代时添加了它)。
但是,如前所述,请记住,Java 版本之间的迭代顺序可能会发生变化,这可能只适用于您的具体示例。
【讨论】: