编辑:现在正确解释了问题。
我有一个hashmap,我想存储一起看到的单词组(键)和它们在一起看到的行(值)。这是我提出的结构:
HashMap<HashSet<String>, HashSet<Integer>> hm= ...
输入:
芒果,香蕉,苹果
apple,banana
桃子,海象
海象,桃子
当我逐行阅读本文时,我会从行中的单词组合中创建新的临时键(尚未插入到hashmap中的哈希集)。每个临时密钥是该行中单词的子集的哈希集。如果我的hashmap中已存在临时密钥,我将通过
检查if(hashmap.containsKey(hashset))
我只是将新行添加到该键的相应值,如果没有,我在hashmap中创建一个新条目并处理它。
我决不改变现有密钥。我只更新了hasmmap中的相应值。
我的hashmap在读取文件的最后应该看起来像这样
[apple,banana] = [1,2]
[peach,walrus] = [3,4]
...
问题在于
if(hashmap.containsKey(hashset))
一段代码并不总是检测现有密钥。为什么是这样?这种结构不允许吗?
谢谢
答案 0 :(得分:7)
这应该可行,但您需要注意键的可变性。如果您更改其中一个键的内容,其哈希码将会更改,并且您的地图将开始执行奇怪的操作。来自Map
的javadoc:
注意:如果将可变对象用作地图,则必须非常小心 键。如果对象的值,则不指定映射的行为 以一种影响等于比较的方式改变 对象是地图中的关键。这一禁令的一个特例是 地图不允许将自己包含为关键字。虽然它 允许地图将自己包含为一个值,极其谨慎 建议:equals和hashCode方法不再明确定义 在这样的地图上。
为避免这种情况,请在创建时立即用Collections.unmodifiableSet()
包裹密钥,或者只使用Guava中的ImmutableSet
。
答案 1 :(得分:4)
您可以,但是一旦您将HashSet
添加为HashMap
的密钥,就不应该再次修改它,因为HashSet.hashCode()
可能会发生变化而您永远找不到你的HashSet
了。换句话说,如果您正在做类似的事情,请确保您的密钥是不可变的HashSets
(另请参阅Matt's answer here)
另一种方法是使用MultiKeyMap
以及来自MultiKey
的commons collections
答案 2 :(得分:1)
@Lukas和@Matt很好地解释了你所遇到的问题
我认为你可以通过使用扩展或使用装饰器模式来创建Hashset
,以一种独立于内容的方式覆盖equals
和hashCode
。
通过这种方式,您可以避免仅针对特定问题引入第三方jar的依赖性