Can i have HashSets as the keys in a HashMap? Suggest an alternative if not

安稳与你 提交于 2019-12-10 13:45:24

问题


Edit: explained the problem properly now.

I have a hashmap where i want to store sets of words seen together (key) and the lines in which they were seen together(value). This is the structure i came up with:

HashMap<HashSet<String>, HashSet<Integer>> hm= ...

for inputs:

  1. mango, banana, apple

  2. apple, banana

  3. peach, walrus

  4. walrus, peach

As I read this, line by line, I make new temporary keys (hashsets not yet inserted into hashmap) from the combination of words in the line. Each temporary key is a hashset of a subset of the words in the line. If a temporary key already exists in my hashmap, which i check by

if(hashmap.containsKey(hashset))

i simply add the new line to that key's corresponding value, if not, I make a new entry in the hashmap and take care of it.

At no point do i change an existing key. I only update their corresponding values in the hasmmap.

my hashmap, at the end of reading the file, should look something like this

[apple, banana]=[1,2]

[peach, walrus]=[3,4]

...

the problem is that the

if(hashmap.containsKey(hashset))

piece of code doesn't always detect existing keys. Why is this? Is this structure not allowed?

Thank you


回答1:


This should work, but you need to watch out for mutability of the keys. If you ever change the contents of one of the keys, its hashcode will change, and your map will start doing strange things. From the javadoc for Map:

Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. A special case of this prohibition is that it is not permissible for a map to contain itself as a key. While it is permissible for a map to contain itself as a value, extreme caution is advised: the equals and hashCode methods are no longer well defined on such a map.

To avoid this, wrap the keys with Collections.unmodifiableSet() immediately upon creation, or just use ImmutableSet from Guava.




回答2:


You can, but once you have added a HashSet as a key to a HashMap you shouldn't modify it again, as the HashSet.hashCode() might change and you'll never find your HashSet again. In other words, if you're doing something like that, be sure that your keys are immutable HashSets (see also Matt's answer here)

An alternative is to use the MultiKeyMap along with a MultiKey from commons collections




回答3:


The problem you have is well explained by @Lukas ans @Matt.
I think you could get away by using extending or using a decorator pattern to create a Hashset that overides equals and hashCode in a way that is independent of the contents.

This way you can avoid introducing dependencies on third party jars just for a specific problem



来源:https://stackoverflow.com/questions/9773846/can-i-have-hashsets-as-the-keys-in-a-hashmap-suggest-an-alternative-if-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!