Ian Worthington Ian Worthington - 1 year ago 158
Java Question

How to get or create new map entry

I'm trying to write a simple utility function to get a value from a Map and, if it's not found to create a new value class and put that in the map.

It seems though very difficult to get the classes of the map's key and value at runtime and the best I can come up with is something horrible along the following lines.

Is there a better way?

private Object getOrCreate( Map<Object, Object> map, Object key, Class<?> mapValueClass ) {
Object value = map.get( key );

if (value == null) {
Constructor<?> con = mapValueClass.getConstructor( key.getClass() );
value = con.newInstance( key );
map.put( key, value );

return value;

Answer Source

You should ckeck out Map::getOrDefault and Map::computeIfAbsent (added in Java 8); those do pretty much exactly what your function is supposed to do. The difference between the two is that getOrDefault will accept an existing instance (created before the method is invoked) and return it if needed, but will not add it to the map, while computeIfAbsend accepts a function for lazily creating a new value, and will also add that value to the map.

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

List<Integer> list1 = map.getOrDefault("foo", Collections.emptyList());
System.out.println(list1); // empty list
System.out.println(map);   // map is still empty

List<Integer> list2 = map.computeIfAbsent("bar", s -> new ArrayList<Integer>());
System.out.println(list2); // empty list
System.out.println(map);   // entry added to map

Assuming that you always want to create a new instance of the Value class with the key as parameter, and assuming that that class actually has such a constructor) you could e.g. use this:

YourClass obj = map.computeIfAbsent(key, YourClass::new);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download