为了账号安全,请及时绑定邮箱和手机立即绑定

为什么只改变 ConcurrentHashMap 中的键值,输出会有差异

为什么只改变 ConcurrentHashMap 中的键值,输出会有差异

小怪兽爱吃肉 2021-12-10 10:51:54
如果您看到此图像,您会发现我刚刚更改了密钥,并且意外地发现了两种不同的结果。在左侧,我发现四个字符串作为输出,而在右侧,我发现只有三个字符串作为输出。有人可以让我理解这种差异吗?
查看完整描述

2 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

您使用ConsurrentHashMap而不是Map像HashMap. 如果您尝试使用其中一个实现并运行您的代码,您会注意到 a ConcurrentModificationException,每当您更新时都会抛出HashMap它,同时对其进行迭代。如果您将该实现更改ConcurrentHashMap为此将更改以下内容:


一个哈希表,支持检索的完全并发性和更新的高预期并发性。[...] 检索操作(包括获取)通常不会阻塞,因此可能与更新操作(包括放置和删除)重叠。检索反映了最近完成的更新操作的结果。


因此,当您迭代Map. 现在,您是否真的可以看到该值的问题可能与实现的迭代顺序有关Map(这可以在 Java 版本之间改变,因为 a 中通常没有迭代顺序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 版本之间的迭代顺序可能会发生变化,这仅适用于您的具体示例。


查看完整回答
反对 回复 2021-12-10
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

ConcurrentHashMap.iterator() 不保证您会或不会在迭代时看到添加的条目。它有一个内部顺序,它会传递条目,如果您在该点之前添加它,您将看不到该条目。

如果您再次迭代这些值,您应该会看到第二个是在第一个条目之前。


查看完整回答
反对 回复 2021-12-10
  • 2 回答
  • 0 关注
  • 154 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信