Well it turns out that LinkedHashMap already has this support built-in if you know what you're doing. There are two parts of this jigsaw:
- Override the protected
removeEldestEntry
method which returns a boolean if the eldest entry should be removed. This method is called for every put with the element that
is eldest according the LRU policy.
- Call the
LinkedHashMap(int capacity, float loadFactor, boolean accessOrder)
constructor. Specifyingtrue
foraccessOrder
means that the order of the elements will be sorted in the order they were last accessed (from least recently used to most recently used).
public class BoundedLruCache<KEY, TYPE> extends LinkedHashMap<KEY, TYPE> { private static final int DEFAULT_INITIAL_CAPACITY = 100; private static final float DEFAULT_LOAD_FACTOR = 0.75; private final int bound; public BoundedLruCache(final int bound) { super(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, true); this.bound = bound; } @Override protected boolean removeEldestEntry(Map.Entry<KEY, TYPE> eldest) { return size() > bound; } }Which is remarkably compact. Once again the JRE library proves to have some nice bits and pieces if you know where to look.
4 comments:
We had to do something very similar several months ago, but ours had to implement a pre-existing cache interface. What we did is slightly different: we wrote our cache as a facade (implementing our cache interface) around a Map. The Map is instantiated as an anonymous inner class instance of LinkedHashMap that overrides removeEldestEntry.
I think override method should be
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > bound;
}
@merereflections: You are correct, I fixed up my example. Many thanks.
@Adam: That's more or less the way I ended up using this code as well, ie. with a class that wraps the cache instance. Thanks for your comment.
Post a Comment