【问题标题】:Java Modifying key object inside mapJava修改地图内的关键对象
【发布时间】:2014-01-04 11:35:02
【问题描述】:

我在使用 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");
}

【问题讨论】:

  • 当然对象是相等的。不同的是修改对象的哈希码和对象所在的相应存储桶(取决于更改的值是否对哈希码有贡献)
  • 好的,我明白了,非常感谢。有什么解决方法吗?有没有办法重新散列?
  • 重新散列HashMap 的唯一方法是添加比当前容量更多的元素。这将迫使它重新计算其哈希值。你真的不应该这样做。
  • 好的,非常感谢,到时我会重新考虑。

标签: java map pass-by-reference stanford-nlp pass-by-value


【解决方案1】:

这在Map Javadoc 中明确记录为危险且不太可能起作用:

注意:如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是映射中的键,则不指定映射的行为。此禁令的一个特殊情况是不允许映射包含自己作为键。虽然允许 map 将自身作为值包含在内,但建议格外小心:equals 和 hashCode 方法不再在此类 map 上得到很好的定义。

【讨论】:

    【解决方案2】:

    问题是在修改键的值时,现在键的哈希码也发生了变化。 HashMap 将首先使用密钥的哈希码来确定它是否存在。修改后的哈希码在映射中不存在,所以它甚至没有尝试使用equals 方法的步骤。这就是为什么在 HashMap 中更改您的关键对象是一个坏主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 2021-12-03
      • 2013-06-07
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多