当我迭代map(HashMap,HashTable,ConcurrentHashMap)时,当我尝试删除特定条目时,在迭代中它仍然使用null值打印它。但每次进入都不会发生这种情况。
public class Test {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
map.put("Pujan", "pujan");
map.put("Swati", "swati");
map.put("Manish", "manish");
map.put("Jayant", "pujan");
System.out.println(map);
for (String string : map.keySet()) {
System.out.println(string+","+map.get(string));
map.remove("Manish");
}
System.out.println(map);
}
}
输出:
{Jayant=pujan, Swati=swati, Manish=manish, Pujan=pujan}
Jayant,pujan
Swati,swati
Pujan,pujan
{Jayant=pujan, Swati=swati, Pujan=pujan}
??第二个Scenarion
//map.remove("Manish");
map.remove("Swati");
输出:
{Jayant=pujan, Swati=swati, Manish=manish, Pujan=pujan}
Jayant,pujan
**Swati,null**
Manish,manish
Pujan,pujan
{Jayant=pujan, Manish=manish, Pujan=pujan}
答案 0 :(得分:1)
ConcurrentHashMap
中的KeySetView
方法会返回iterator
,其中weakly consistent iterator
,换句话说,它返回的ConcurrentHashMap#keySet()
是创建时集的快照。
来自map.get
Java文档
视图的迭代器和分裂器是弱一致的
但是当你调用<asp:GridView ID="GridView1" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="White"
RowStyle-BackColor="#A1DCF2" AlternatingRowStyle-BackColor="White" AlternatingRowStyle-ForeColor="#000"
runat="server" AutoGenerateColumns="false" AllowPaging="true" OnPageIndexChanging="OnPageIndexChanging">
<Columns>
<asp:BoundField DataField="isbn" HeaderText="isbn" ItemStyle-Width="150px" />
<asp:BoundField DataField="display_name" HeaderText="bookName" ItemStyle-Width="100px" />
<asp:BoundField DataField="authorName" HeaderText="authorName" ItemStyle-Width="100px" />
</Columns>
时,更改是可见的,这意味着map.get将返回null,因为你要求一个不存在的密钥
答案 1 :(得分:1)
查看keySet()[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#keySet--][1]
的JavaDocs(假设是Java8)返回此地图中包含的键的Set视图。该集由地图支持,因此对地图的更改将反映在集中,反之亦然。该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从此映射中删除相应的映射。它不支持add或addAll操作。
视图的迭代器和分裂器非常一致。
链接到:
它们可以保证遍历元素,因为它们在构造时只存在一次,并且可能(但不保证)反映构造后的任何修改。
这就是你所看到的。
管理for循环的迭代器并不能保证在构造视图后反映更改。
视图始终由4个原始条目构成。现在,在使用&#34; Manish&#34;的示例中,只是迭代器 反映了修改,因此字符串永远不会将Manish视为值,而您永远不会map.get("Manish")
。唉,使用Swati迭代器并没有反映修改,它仍然给你&#34; Swati&#34;作为第二个元素,尽管数据始终是一致的:根据JavaDocs,map.get("Swati")
确实反映了这一变化。
我还没有读过ConcurrentHashMap.MapEntry
中的代码(你应该),但之所以会出现这种情况的原因是&#34; Swati&#34;而不是&#34; Manish&#34;很有可能是以下几点。
此时,执行iterator.next()会返回current
=&#34; Swati&#34; (如果元素从地图中消失,则显示随后的map.get()
)
如果你删除&#34; Manish&#34; (或者#34; Pujan&#34;),迭代器能够更新nodes
。但如果你删除&#34; Swati&#34;由于current
已经加载了该密钥,因此已经太晚了。