Simple Java Tip: Lazy Loading HashMap

I am pretty sure you have seen this “lazy loading”/caching Java idiom or one of it’s many alternatives quite often:

Map cache = new HashMap();

public Entity getItem(String name) {
if(!cache.containsKey(name)) {
cache.put(name, new Entity(name));
}
return cache.get(name);
}

Here is another way of doing the same thing, the LazyHashMap calls the lazyHandler when it needs to get a missing value:

public class LazyHashMap extends HashMap{
private Functor1 lazyHandler;

public LazyHashMap(Functor1 lazyHandler) {
this.lazyHandler = lazyHandler;
}

@Override
public V get(Object key) {
if (!containsKey(key)) {
K k = (K) key;
put(k, lazyHandler.invoke(k));
}
return super.get(key);
}
}


Functor1 is simple interface:

public interface Functor1 {
R invoke(A1 a1);
}

A decorator pattern could be used instead of extending the HashMap class.

class LazyMapDecorator implements Map {
private final Map m;
private final Functor1 lazyHandler;

public LazyMapDecorator(Map m, Functor1 lazyHandler) {
this.m = m;
this.lazyHandler = lazyHandler;
}

public V get(Object key) {
if (!containsKey(key)) {
K k = (K) key;
m.put(k, lazyHandler.invoke(k));
}
return m.get(key);
}
...

And here is an example:

LazyHashMap entityCache = 
new LazyHashMap(new Functor1() {
@Override
public Entity invoke(String a1) {
return new Entity("Bozo");
}
});

entityCache.get("Bozo");

This trick lets you retrofit caching into your code without having to encapsulate the map calls into “accessor” like methods, just decorate an existing map or change it to a lazy one.

This technique is an example of functional programming in Java, read my previous post or ask a search engine about it.

Leave a Reply

Your email address will not be published. Required fields are marked *