问题
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:
mango, banana, apple
apple, banana
peach, walrus
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