简体   繁体   中英

Best way to access a Map of Map

Consider the following situation:

I have a map with String as a key and another Map as a value. Now the Map in the value is also a Map with a String as key and a Map as value. We have some n levels like this and the final level has a Map with String as a key and String as a value. Now suppose, I have the list of keys for each level. I have to get the final String value.

This is how I have thought to implement it in java:

Object q = initialMap; 
for(String key : keyList)
{
    Map x = (Map)q;
    q = x.get(key);
}
return (String)q;

Is this the right way to approach this? I get the unchecked conversion warning with this. Is there any better way of doing this?

I think I understand you problem, you obtain from a file a Map of String to Map of String to Map of ... etc. Something like this:

 Map<String, Map<String, Map<String, Map<String, String>>>> initialMap;

What is not clear in your question is if you know how many levels of map there will be. If yes, then just write your initialMap like I just did (for 4 levels of Maps) for the number of levels you need.

If you don't know by advance how much levels you have then it's more difficult. In that case, your algorithm is sound. I would only make it more generics like this:

Object q = initialMap; 
for(String key : keyList)
{
    Map<String, ?> x = (Map<String, ?>)q;
    q = x.get(key);
}
return (String)q;

But this will always give you a warning, that you will have to suppress with adding @SuppressWarnings("unchecked") to the method.

You can try abstracting this away in a method.

Edit : there is a way to actually abstract it completely in utility classes. I would call what you want a kind of recursive Map. Any of your Map is either a map from String to String or map to String to a recursive map. This can be abstracted this way:

interface IRecursiveMap {
  String get(List<String> keyList);
}

class RecursiveMap implements IRecursiveMap{
  Map<String, IRecursiveMap> map;

  @Override
  public String get(List<String> keyList) {
    String key = keyList.get(0);
    return map.get(key).get(keyList.subList(1, keyList.size()));
  }
}

class ValueMap implements IRecursiveMap{
  Map<String, String> map;

  @Override
  public String get(List<String> keyList) {
    String key = keyList.get(0);
    return map.get(key);
  }
}

So IRecursiveMap is the interface that defines the common behaviour of your maps: the ability to get something from a list of keys. RecursiveMap is the implementation that maps a String to another IRecursiveMap and ValueMap is the last map of the recursion, which actually maps String to String.

The good in that implementation is :

  • The code use generics properly and the data is fully typed. It means you don't have any more generic warnings.
  • All the logic to store stuff in this chain of maps is abstracted in a few utility classes.

On the other hand the downside is that it may be a little complicated to fill your map, but again it can be done recursively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM