Java Generic Cache Map with Expiration

If you have many configuration files stored on S3 or on some other resource, you don’t want your Java application to request them each time directly from the cloud because it’s not efficient in terms of performance. You need to use some sort of Cache to store all the configuration. When your application will request the file for the first time it will be stored in cache for some period. Next time that configuration will be read from memory, not from the cloud. Thus your application will work smoother.

In this article you’ll see the implementation of such generic CachMap.

public class CacheMap<K,V> {
	private static class CacheItem<V> {
		final V v;
		final long expirationTime;
		public CacheItem(V v, long expirationTime) {
			this.v = v;
			this.expirationTime = expirationTime;
		}
		boolean isExpired() {
			return System.currentTimeMillis() > expirationTime;
		}
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((v == null) ? 0 : v.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			CacheItem<?> other = (CacheItem<?>) obj;
			if (v == null) {
				if (other.v != null)
					return false;
			} else if (!v.equals(other.v))
				return false;
			return true;
		}
		@Override
		public String toString() {
			return "CacheItem [v=" + v + ", expirationTime=" + expirationTime + "]";
		}
	}
	
	final Map<K, CacheItem<V>> cache;
	final Function<K, CacheItem<V>> loader;
	
	public CacheMap(long expirationMillis, Function<K, V> loader) {
		this.cache = new ConcurrentHashMap<>();
		this.loader = k->new CacheItem<>(loader.apply(k), System.currentTimeMillis() + expirationMillis);
	}
	
	public V get(K k) {
		return cache.compute(k, (kk,vv)->(vv==null || vv.isExpired()) ? loader.apply(k) : vv).v;
	}
	
	public void remove(K k) {
		cache.remove(k);
	}
	
	public void clear() {
		cache.clear();
	}
}

And this is how you initialize the CacheMap:

CacheMap<String, String> configurationCache = new CacheMap<>(60 * 10 * 1000L, this::getYourConfigurationFileMethod);

 

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.