I have a Java class with private static maps used to store information during the execution of the application. I would only ever put a key/value once into the Map but the map value may be read many times.
So the way I have it now, the code does a get and checks for null. If null then I gather the data I need and put it into the map. Subsequent calls by the client code would be guaranteed to get the value from the map. The client would not need to do null checks.
The reason for this is that getting the data to put in the map could be expensive so I only want to do this once per key.
Is there any pattern for this? I can’t seem to find anything out there that discusses this situation.
TIA
Here’s a totally non-thread-safe example:
public class TestWorm {
private static Map<String, Object> map = new HashMap<String, Object>(32);
public Object getValue(String key) {
if (map.get(key) != null) {
return map.get(key);
}
// do some process to get Object
Object o = new Object();
map.put(key, o);
return o;
}
}
Your best bet is ConcurrentHashMap and it’s putIfAbsent method.
Your implementation is not thread safe. To make it thread safe, declare field final, change implementation class to ConcurrentHashMap and that is enough, if you don’t care if sometimes values will be computed and stored several times (this would be rare: in case two thread simultaneously enter get and corresponding value is not yet computed. This is usually good trade off, as usually the most common case is when you have something in the cache. And in this case you do not use any extra synchronization to retrieve existing value.)
If you want to make sure that there is at most one value present in your application for the given key you can further extend your implementation by using putIfAbsent, instead of put.
Another way to implement this would be to use guava library: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/MapMaker.html
Yet another way to do that would be to use computeIfAbsent of ConcurrentHashMapV8 (http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/ConcurrentHashMapV8.java?view=markup) which will someday appear in Java 8.