【问题标题】:Java Hashtable .containsKey(String key) is returning true even when the strings and hashcodes are different... How?即使字符串和哈希码不同,Java Hashtable .containsKey(String key) 也会返回 true ......如何?
【发布时间】:2011-08-03 16:33:34
【问题描述】:

我目前在 java 中的 Hashtable 存在一些问题,其中 FEightPuzzle 是我创建的一个类。

在我的类中,我有一个字符串,用于存储每个实例的密钥。现在,在我的程序中,当我在 Hashtable 中检查重复实例时,我有时会“找到”一些,而实际上找到的实例是不同的。

以我调用 bol.containsKey(current.key) 为例,其中 bol 是 HT,current 是 FEightPuzzle。

如果这是真的,我会检查键的值,它们是

current.key =
"8 14 11 0 6 12 13 1 10 4 5 9 15 2 3 7"

bol.get(current.key).key =
"12 8 4 0 13 9 5 1 14 10 6 2 15 11 7 3"

有价值观

current.key.hashCode() = -950607924

bol.get(current.key).key.hashCode() = -1856769042

很抱歉打扰你,但这个问题真的很困扰我,这是我今晚最不想说实话(你不喜欢那个)......任何提示或答案将不胜感激!

【问题讨论】:

  • 附带说明,Hashtable 已过时,最好使用HashMap(或ConcurrentHashMap,如果您需要线程安全)。
  • 您是否可能正在更改已添加到地图中的项目的键(不删除并重新添加它们以保持地图完整性)?
  • 好问题,但不,我认为这不可能。实例的状态在初始化时设置,从那时起没有进行任何更改 - 这就是创建密钥的地方
  • 你能贴出将对象添加到 HT 的代码吗?

标签: java string key hashtable hashcode


【解决方案1】:

我已重读您的问题,据我了解,您有以下问题:

你会的

bol.containsKey(current.key)

检查current是否已经在bol中。

当它返回 true 时,您希望 current.key 映射到的值确实应该是 current,但正如您的哈希码所示,它不是。

问题很可能是以下之一:

  1. 一开始你没有把拼图对象正确放入哈希表中。

    你应该这样做

    bol.put(somePuzzle.key, somePuzzle)
    
  2. 当拼图在地图中时,您更改了钥匙。这是不允许的。

    在映射中添加条目后,如果不删除/重新插入映射,则不能更改键。

    Hashtable 将根据您在插入时提供的键查找对象。

  3. 您不小心为多个不同的拼图对象提供了相同的密钥(在这种情况下,一个 put 将覆盖前一个)


一个建议是让 FEightPuzzle 覆盖 hashCode 和 equals 并使用 HashSet 而不是 Hashtable。

【讨论】:

  • 我之前也打错了,现在已经修复了,这些是实际键中的值。 FEightPuzzle toString 方法与此完全不同。
  • 有点,我看了看,他们说 java HT 使用一个键,但是对于相同的键,额外的对象被分桶,有点像一个键可以使用一个键指向多个对象数组或链表。问题是这对于 java HT api 中描述的内容没有意义,因为它们清楚地表明每个键应该唯一地映射到单个对象。我发现这种情况发生的唯一原因是当我导出列表并尝试将它们全部重新输入到 HT 时,HT 只填了一半,因为它(我假设)正在覆盖具有相同密钥的旧对象......跨度>
  • 天哪,看来我放入 HT 的第一个值使用了错误的键。非常感谢您指出... HT 中有超过 200,000 个对象,这只是第一个给我错误的对象。谢谢,真是一种解脱。
  • @Sekm:不,哈希表不允许同一个键有多个值。链表分桶仅用于具有相同哈希码的不同键(或偶然映射到同一桶的不同哈希码)。
  • @Paŭlo Ebermann 这让事情变得更清楚了,谢谢你的解释 - 我想知道在这些情况下会发生什么(看到哈希码似乎存储为整数),我认为在那些是否会使用equals方法来获得100%的准确率?
【解决方案2】:

我想你可能误解了Hashtable 的作用。它将键映射到值。因此,在您的密钥上调用get(key) 将返回您使用put(key, value) 提供的值。现在,如果您总是输入与键相同的值,那么您应该期待同样的事情,但是在这种情况下,您只需要一个 HashSet。如果您为不同的键输入相同的值,它将允许这样做。 Hashtable 中只有键是唯一的(和 HashMap 相同)。

【讨论】:

  • Nono 我明白了,我只是在第一次发布问题时打错了,对不起,这是我的错误
  • 啊,我明白了。所以看起来您将键存储为值对象的成员?您是否可能重用这些值对象并将键设置为与另一个键使用的相同实例?如果您可以包含一些代码 sn-ps 可能会对这里的人们提供帮助有所帮助。
猜你喜欢
  • 2016-05-31
  • 2018-05-29
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多