2

How can I create a "multidimensional" HashMap with HashMaps as Value without initializing every HashMap like you see below?

HashMap<Integer, String> DenmarkBasic = new HashMap<Integer, String>();
DenmarkBasic.put(1, "http://website1.com/");
DenmarkBasic.put(2, "http://website2.com/");

HashMap<Integer, String> DenmarkMisc = new HashMap<Integer, String>();
DenmarkMisc.put(1, "http://website1.com/");
DenmarkMisc.put(2, "http://website2.com/");

HashMap<String, HashMap<Integer, String>> DenmarkPanel = new HashMap<String, HashMap<Integer, String>>();
DenmarkPanel.put("Basic", DenmarkBasic);
DenmarkPanel.put("Misc", DenmarkMisc);

HashMap<String, HashMap<String, HashMap<Integer, String>>> NordicCountry = new HashMap<String, HashMap<String, HashMap<Integer, String>>>();
NordicCountry.put("Denmark", DenmarkPanel);
NordicCountry.put("Sweden", SwedenPanel);

HashMap<String, HashMap<String, HashMap<String, HashMap<Integer, String>>>> Market = new HashMap<String, HashMap<String, HashMap<String, HashMap<Integer, String>>>>();
Market.put("Nordic", NordicCountry);

I just want to use a loop, because it would be too much Maps.

Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
  • Please read the answers below, especially on why you should think about another structure than nested maps. However, there might be cases where you need them (and in fact JSONObject _is_ a map). There's a thing to consider though: whenever possible use interfaces, so `Map>` etc. Also, as of Java 8 there are useful helper methods that can reduce errors and code, e.g. putting a value into such a nested map could become `map.computeIfAbsent("outer key", k -> new HashMap<>()).put("inner key", "value"))` which creates the nested map only if it doesn't exist. – Thomas Oct 01 '18 at 12:59
  • Similar to this scenario,Please read the answer provided by dimo414 https://stackoverflow.com/questions/15626280/java-initialize-a-hashmap-of-hashmaps – Manasa Oct 01 '18 at 12:10

2 Answers2

4

Don't do that!

Nesting hash maps makes your code very very complicated very very quickly. Just look at how long your type names are getting.

You should write the data in another format, like JSON, and then parse it.

Your JSON would look something like this:

{
    "Market" : {
        "Nordic": {
             "Denmark": {
                  "Basic": ["website1.com", "website2.com"],
                  "Misc": ["website1.com", "website2.com"]
              },
             "Sweden": {
                  "Basic": ["website1.com", "website2.com"],
                  "Misc": ["website1.com", "website2.com"]
              },
         }
    }
}

And then you use a JSON parser to parse it. For example, as shown in this answer, you can use org.json. To get the list of basic Denmark websites:

jsonObject
    .getJSONObject("Market")
    .getJSONObject("Nordic")
    .getJSONObject("Denmark")
    .getJSONArray("Basic")

There are also other libraries mentioned in that post. Find the one you like the most and use it!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Good, but still an annoyingly procedural way of accessing the data. It's effectively [stringly typed](http://wiki.c2.com/?StringlyTyped). Better to use classes and some mapping framework. My preference is usually Jackson, and I would prefer YAML to JSON – Michael Oct 01 '18 at 12:26
  • @Michael The idea of using classes came to my mind as well, but I didn't know the details of OP's model, so I couldn't write classes that represent OP's model. – Sweeper Oct 01 '18 at 14:40
1

It's generally a bad practice to create such nested structures (like map contains a map, or list containing maps, etc.), so Guava comes with new collections, you can find there things like multimap, multiset which will help you write better, safer and future-proof code. Try it out, such structures are availalbe in Guava and Apache Collections

https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap

agilob
  • 6,082
  • 3
  • 33
  • 49