我遇到了JAVA地图的问题。我在地图中输入一个对象作为键。然后我修改了键,地图不再将对象视为地图的键。即使对象内部的键已相应修改。
我正在使用StanfordNLP的对象CoreLabel
,但它适用于我猜的一般情况。
Map <CoreLabel, String> myMap = new HashMap...
CoreLabel key = someCreatedCoreLabel
myMap.put(key, someString)
myMap.get(key) != null ----> TRUE
key.setValue("someValue");
myMap.get(key) != null ----> FALSE
我希望我足够清楚。问题是为什么最后一个陈述是假的?我不是一个非常有经验的程序员,但我希望它是真的。也许与CoreLabel
对象有关?
我检查.equals()
是否仍然成立,实际上是
for(CoreLabel token: myMap.keySet()) {
if(key.equals(token))
System.out.println("OK");
}
答案 0 :(得分:7)
这在Map
Javadoc中明确记录为危险且不太可行:
注意:如果将可变对象用作映射键,则必须非常小心。如果在对象是地图中的键的情况下以影响等于比较的方式更改对象的值,则不指定映射的行为。这种禁令的一个特例是地图不允许将自己作为关键词包含在内。虽然允许地图将自己包含为值,但建议极其谨慎:在这样的地图上不再定义equals和hashCode方法。
答案 1 :(得分:3)
问题是在修改密钥的值时,现在密钥的哈希码也发生了变化。 HashMap
将首先使用密钥的哈希码来确定它是否存在。修改后的哈希码在地图中不存在,因此它甚至没有尝试使用equals
方法的步骤。这就是为什么在HashMap
处更改关键对象时,这是个坏主意。