How do I access nested HashMaps in Java?

120,016

Solution 1

You can do it like you assumed. But your HashMap has to be templated:

Map<String, Map<String, String>> map = 
    new HashMap<String, Map<String, String>>();

Otherwise you have to do a cast to Map after you retrieve the second map from the first.

Map map = new HashMap();
((Map)map.get( "keyname" )).get( "nestedkeyname" );

Solution 2

You can get the nested value by repeating .get(), but with deeply nested maps you have to do a lot of casting into Map. An easier way is to use a generic method for getting a nested value.

Implementation

public static <T> T getNestedValue(Map map, String... keys) {
    Object value = map;

    for (String key : keys) {
        value = ((Map) value).get(key);
    }

    return (T) value;
}

Usage

// Map contents with string and even a list:
{
  "data": {
    "vehicles": {
      "list": [
        {
          "registration": {
            "owner": {
              "id": "3643619"
            }
          }
        }
      ]
    }
  }
}
List<Map> list = getNestedValue(mapContents, "data", "vehicles", "list");
Map first = list.get(0);
String id = getNestedValue(first, "registration", "owner", "id");

Solution 3

Yes.

See:

public static void main(String args[]) {

    HashMap<String, HashMap<String, Object>> map = new HashMap<String, HashMap<String,Object>>();
    map.put("key", new HashMap<String, Object>());
    map.get("key").put("key2", "val2");

    System.out.println(map.get("key").get("key2"));
}

Solution 4

If you plan on constructing HashMaps with variable depth, use a recursive data structure.

Below is an implementation providing a sample interface:

class NestedMap<K, V> {

    private final HashMap<K, NestedMap> child;
    private V value;

    public NestedMap() {
        child = new HashMap<>();
        value = null;
    }

    public boolean hasChild(K k) {
        return this.child.containsKey(k);
    }

    public NestedMap<K, V> getChild(K k) {
        return this.child.get(k);
    }

    public void makeChild(K k) {
        this.child.put(k, new NestedMap());
    }

    public V getValue() {
        return value;
    }

    public void setValue(V v) {
        value = v;
    }
}

and example usage:

class NestedMapIllustration {
    public static void main(String[] args) {

        NestedMap<Character, String> m = new NestedMap<>();

        m.makeChild('f');
        m.getChild('f').makeChild('o');
        m.getChild('f').getChild('o').makeChild('o');
        m.getChild('f').getChild('o').getChild('o').setValue("bar");

        System.out.println(
            "nested element at 'f' -> 'o' -> 'o' is " +
            m.getChild('f').getChild('o').getChild('o').getValue());
    }
}

Solution 5

As others have said you can do this but you should define the map with generics like so:

Map<String, Map<String, String>> map = new HashMap<String, Map<String,String>>();

However, if you just blindly run the following:

map.get("keyname").get("nestedkeyname");

you will get a null pointer exception whenever keyname is not in the map and your program will crash. You really should add the following check:

String valueFromMap = null;
if(map.containsKey("keyname")){
  valueFromMap = map.get("keyname").get("nestedkeyname");
}
Share:
120,016
Mridang Agarwalla
Author by

Mridang Agarwalla

I'm a software developer who relishes authoring Java and Python, hacking on Android and toying with AppEngine. I have a penchant for development and a passion for the business side of software. In between all the work, I contribute to a number of open-source projects, learn to master the art of cooking Asian cuisine and try to stay sane while learning to fly my Align Trex-600 Nitro Heli.

Updated on July 09, 2022

Comments

  • Mridang Agarwalla
    Mridang Agarwalla almost 2 years

    I have a HashMap in Java, the contents of which (as you all probably know) can be accessed by

    HashMap.get("keyname");
    

    If a have a HashMap inside another HashMap i.e. a nested HashMap, how would i access the contents? Can i do this like this, inline:

    HashMap.get("keyname").get("nestedkeyname");
    

    Thank you.

  • Torben
    Torben about 5 years
    The tail recuresion and array copying is completely unnecessary.
  • Adam DeWitt
    Adam DeWitt about 5 years
    Torben - please explain.
  • user12193365
    user12193365 over 4 years
    output is : {dog2={Age=6, Name=pumpkin, Food=ppl's Ass}, dog1={Age=3, Name=Breezi, Food=Chicken liver}} 3
  • JGFMK
    JGFMK over 2 years
    After = can't you just do new HashMap<>(); Less typing.. (May have been asked in the pre 1.8 era. Then it would have applied).
  • iBug
    iBug over 2 years
    should be the selected answer.