9

I have a requirement where I need to map a set of configurations with a set of values, ideally denoted by a Map<Map<String, Object>, Map<String, Object>> structure.

Both the configurations & the values part of the main Map are arbitrary & hence, I am unable to use a concrete class.

Please provide some feedback on this structure. Can a Map be used as a key for another Map. Doing a bit of research, I was able to establish that the Map's equals method utilizes all underlying Keys & Values to deem two Maps as equal. Also, the HashCode of a Map is based on the Hashcodes of the Map's Keys. This IMO should suffice the minimum requirements of using a Map as a key.

I would still like someone to validate this before I go ahead with the implementation. In case there is a better solution / design that someone can suggest, please feel free to do so.

EDIT

I ended up using a simple tilde ('~') & pipe ('|') separated String as the key & deconstructed it whenever needed. Thanks to all who helped.

Sumit
  • 540
  • 9
  • 20
  • 7
    You do not have that requirement. You only think you do. – Raedwald Feb 17 '17 at 09:25
  • You could probably somehow hack it together, but I think you should step back and be 100% certain that you can not use a String or a Pojo as the key. – Murat Karagöz Feb 17 '17 at 09:26
  • 3
    Composing maps of maps is a clue that you should create some separate classes. – Arnaud Denoyelle Feb 17 '17 at 09:27
  • "*I ended up using a simple tilde ('~') & pipe ('|') separated String*" stringly-typed keys make me sad :'( - if you have structured data, use a structured type (i.e. a dedicated key type), don't mangle that structure into a string. [`@AutoValue](https://github.com/google/auto/tree/master/value) makes it very easy to quickly define such types. – dimo414 Feb 22 '17 at 11:07

1 Answers1

21

Yes, a HashMap can be used as a key to another map, as the class properly overrides .equals() and .hashCode().

However it's broadly speaking a bad idea to use mutable types (such as HashMap) as Map keys or Set elements, because you violate the invariants these classes expect if the objects are mutated while in the collection.

While not quite what you're looking for, Guava offers several additional data structures such as Multiset, MultiMap, BiMap, Table which may be useful. They also offer immutable collections such as ImmutableMap which (because they can't be mutated) are safer to use as a Map key. Which isn't to say you should do so, simply that it's safe (if the keys and values are also immutable).

Consider posting a question exploring the problem that lead you to conclude a Map<Map<K, V>, Map<K, V>> structure was what you needed. You may get better answers to that question.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • This makes a lot of sense. I had completely overlooked immutability. Will look into immutable collections. – Sumit Feb 17 '17 at 10:32
  • 1
    @Sumit, glad to help, but please also consider alternative data structures - nested maps are generally a code smell, and can quickly become difficult to work with. – dimo414 Feb 18 '17 at 17:35