
Java Simple Cache
There are plenty of high-quality libraries with a lot of features that are freely available out there that can help you but sometimes the overhead does not really worth it. You have probably faced the same issue as I have faced looking for simple lightweight in-memory caching code. A simple code that can help you deal with the basic caching issues in a single instance application scope. I think the following class can be useful to use for simple projects.
public class SimpleCache {
private HashMap<String, CacheItem<?>> cache = new HashMap<>();
private static SimpleCache simpleCache;
private final static Integer DEFAULT_EXPIRE_DURATION_MIN = 30;
private SimpleCache(){}
public static SimpleCache getInstance(){
if( simpleCache == null ) simpleCache = new SimpleCache();
return simpleCache;
}
public <T> T getCacheItem( String key ) throws CacheItemNotFound {
CacheItem<T> cacheItem = (CacheItem<T>) cache.get(key);
if( cacheItem == null ) throw new CacheItemNotFound();
if( cacheItem.isEvicted() || cacheItem.getExpireDateTime().compareTo( new Date()) < 0 ){
cacheItem.setCacheContent(cacheItem.getFunction().execute());
}
return cacheItem.getCacheContent();
}
public <T> T cacheItem( String key, CacheFunctionalInterface<T> function){
return this.<T> cacheItem(key, function, Calendar.MINUTE, DEFAULT_EXPIRE_DURATION_MIN);
}
public <T> T cacheItem( String key, CacheFunctionalInterface<T> function, Date expireDateTime){
CacheItem<T> cacheItem = (CacheItem<T>) cache.get(key);
if( cacheItem == null ){
cacheItem = new CacheItem<>();
cacheItem.setFunction(function);
cacheItem.setExpireDateTime(expireDateTime);
cacheItem.setLastUpdateDateTime(new Date());
cacheItem.setCacheContent(function.execute());
cache.put(key,cacheItem);
} else {
if( cacheItem.isEvicted() || cacheItem.getExpireDateTime().compareTo( new Date()) < 0 ) {
cacheItem.setExpireDateTime(expireDateTime);
cacheItem.setLastUpdateDateTime(new Date());
cacheItem.setCacheContent(function.execute());
}
}
return cacheItem.getCacheContent();
}
public <T> T cacheItem(String key, CacheFunctionalInterface<T> function, Integer field, Integer amount ){
Calendar expireDateTimeCalendar = Calendar.getInstance();
expireDateTimeCalendar.add( field, amount );
return this.<T> cacheItem(key, function, expireDateTimeCalendar.getTime());
}
public void evict( String key ){
if( cache.get(key) != null ) cache.get(key).setEvicted(true);
}
private static class CacheItem<T> {
private Date expireDateTime = new Date();
private Date lastUpdateDateTime = new Date();
private boolean evicted = false;
private T cacheContent;
private CacheFunctionalInterface<T> function; // getters and setters
}
public static interface CacheFunctionalInterface<T> {
public T execute();
}
public static class CacheItemNotFound extends Exception {
public CacheItemNotFound(){
super();
}
}
}
SimpleCache is a Singelton class and utilizing it is pretty simple as well, you can get an instance from the class using the proper method, and then just by calling the “getCacheItem” method you will be able to add a value to your cache. Since the implementation is generic the return type can be any reference type object based on your requirements.
SimpleCache cache = SimpleCache.getInstance();
String cachedValue = cache.cacheItem("some.key",() -> {
// implementation for cache value update
// e.g. data retrieval from DB or thirdparty API
return "value";
}, Calendar.MINUTE, 5);
String cachedValueCopy = cache.getCacheItem("some.key");
The first row is used to get the instance of the cache object. the “cacheItem” method has different implementations. This implementation requires a key which is used later to retrieve the cached data, and the implementation of CacheFunctionalInterface which is used for updating the cached data, the duration type, and the duration amount.
Feel free to contribute, change and improve the code as necessary. you can find the project on Github.