I want to create a generic function that takes any Map & a String key, if the key is not present in the map, then it should create a new instance of the Value Type (which is passed) & put it in the map & then return it.
Here is my implementation
public <T> T getValueFromMap(Map<String, T> map, String key, Class<T> valueClass){
T value = map.get(key);
if (value == null){
try {
value = valueClass.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
map.put(key, value);
}
return value;
}
It works if I use it with a normal (not generic) List as the value type,
Map<String,List> myMap;
List value = getValueFromMap(myMap, "aKey", List.class) //works
but not with generic type lists
Map<String,List<String>> myMap;
List<String> value = getValueFromMap(myMap, "aKey", List.class) //does not work
Also if I try to make Map<String, T>
map parameter generic by changing it to Map<String, T<?>>
it complains that the type T is not generic; it cannot be parameterized with arguments <?>
Can the generic parameters be themselves made generic?
Is there any way to create function with above mentioned requirements?
~Update
Thanks for all the insightful answers everyone.
I have verified that the accepted solution works for any value type with this code
Map<String, Map<String, List<String>>> outer =
new HashMap<String, Map<String,List<String>>>();
Map<String, List<String>> inner = getValueFromMap(outer, "b",
(Class<Map<String, List<String>>>)(Class<?>)HashMap.class);
List<String> list = getValueFromMap(inner, "a",
(Class<List<String>>)(Class<?>)ArrayList.class);
You need most specific types which is String
in your case. List.class
returns you Class<List<?>>
in your case you need specific type so you will need to add cast Class<List<String>>
Map<String,List<String>> myMap = new HashMap<String, List<String>>();;
List<String> value = getValueFromMap(myMap, "aKey",
(Class<List<String>>)(Class<?>)ArrayList.class) ;
Now if you invoke method like below
getValueFromMap(myMap, "aKey", List.class)
^^^T is List<String> ^^^ T is List<?> wild char since List.class
will return you Class<List<?>>
So your defination of T
is causing confusion to Compiler so you are getting compile error.
You can not create instance of List.class
since it is interface you will need implemention class of it so call method with ArrayList.class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With