为什么HashMap“不包含”仅在内部更改的键?

时间:2011-08-24 17:15:20

标签: java collections map identity

在我的程序中,我有一个HashMap。它将字符串的HashSets作为其键,将字符串的PriorityQueues作为其值。当我更改其中一个键的内容时,它不再保留为HashMap的成员。这对我来说似乎很奇怪,因为我没有更改密钥的引用。我只是改变了它的内容。请查看以下代码段:

HashMap<HashSet<String>, PriorityQueue<String>> myHashMap=new HashMap<>();

HashSet<String> myHashSet=new HashSet<>();
myHashSet.add("abc");
myHashSet.add("mnq");
myHashSet.add("al;ksghl");

PriorityQueue<String> myPriorityQueue=new PriorityQueue<>();
myPriorityQueue.add("3h4");
myPriorityQueue.add("lskdjf");

myHashMap.put(myHashSet, myPriorityQueue);

if(myHashMap.containsKey(myHashSet))
    System.out.println("Yes!");

myHashSet.remove("abc");

if(myHashMap.containsKey(myHashSet))
    System.out.println("Yes!");

基本上,我希望看到两个“是的!”,实际上,它只打印一个。我做了一个彻底的调试,并意识到myHashSet的参考号在删除其中一个成员后没有改变。所以,这个程序没有理由不打印第二个“是的!”。

非常感谢任何形式的帮助。

2 个答案:

答案 0 :(得分:6)

更改集的内容会更改其标识和哈希码。由于地图使用equalshashCode来查找并比较其键,因此会破坏地图的完整性,而不会再找到该地图中显示的内容。

引用the Javadoc

  

注意:如果将可变对象用作映射键,则必须非常小心。如果在对象是地图中的关键字时,以影响equals比较的方式更改对象的值,则不会指定地图的行为。

尝试添加行

System.out.println(myHashSet.hashCode());

remove来电之前和之后看到差异。

答案 1 :(得分:1)

关键字的哈希/等于的Hashmap键(已经指出,正在改变)。如果您关心身份,则应使用java.util.IdentityHashMap