Reputation: 263
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?
Upvotes: 1
Views: 122
Reputation: 15538
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 :
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.
Upvotes: 1