DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone >

Time Based Cache

Snippets Manager user avatar by
Snippets Manager
·
Aug. 03, 06 · · Code Snippet
Like (0)
Save
Tweet
5.47K Views

Join the DZone community and get the full member experience.

Join For Free
A simple time based cache build around a map store.


import java.util.Map;
import java.util.WeakHashMap;

/**
 * Simple time-based cache.
 */
public class SimpleCache {
	private long maxAge;
	private Map store;

	/**
	 * Instanciate a cache with max age of 1 hour and a WeakHashMap as store.
	 * @see java.util.WeakHashMap
	 */
	public SimpleCache() {
		this.maxAge = 1000 * 60 * 60;
		this.store = new WeakHashMap();
	}
	
	/**
	 * @param maxAge maximum age of an entry in milliseconds
	 * @param store map to hold entries
	 */
	public SimpleCache(long maxAge, Map store) {
		this.maxAge = maxAge;
		this.store = store;
	}
	
	/**
	 * Cache an object.
	 * @param key unique identifier to retrieve object
	 * @param value object to cache
	 */
	public void put(Object key, Object value) {
		store.put(key, new Item(value));
	}
	
	/**
	 * Fetch an object.
	 * @param key unique identifier to retrieve object
	 * @return an object or null in case it isn't stored or it expired
	 */
	public Object get(Object key) {
		Item item = getItem(key);
		return item == null ? null : item.payload;
	}
	
	/**
	 * Fetch an object or store and return output of callback.
	 * @param key unique identifier to retrieve object
	 * @param block code executed when object not in cache
	 * @return an object
	 */
	public synchronized Object get(Object key, Callback block) {
		Item item = getItem(key);
		if (item == null) {
			Object value = block.execute();
			item = new Item(value);
			store.put(key, item);
		}
		return item.payload;
	}
	
	/**
	 * Remove an object from cache.
	 * @param key unique identifier to retrieve object
	 */
	public void remove(Object key) {
		store.remove(key);
	}
	
	/**
	 * Get an item, if it expired remove it from cache and return null.
	 * @param key unique identifier to retrieve object
	 * @return an item or null
	 */
	private Item getItem(Object key) {
		Item item = (Item) store.get(key);
		if (item == null) {
			return null;
		}
		if (System.currentTimeMillis() - item.birth > maxAge) {
			store.remove(key);
			return null;
		}
		return item;		
	}

	/**
	 * Value container.
	 */
	private static class Item {
		long birth;
		Object payload;
		Item(Object payload) {
			this.birth = System.currentTimeMillis();
			this.payload = payload;
		}
	}
	
	/**
	 * A visitor interface.
	 */
	public static interface Callback {
		Object execute();
	}
}


And a couple of junit tests:


import java.util.HashMap;

import junit.framework.TestCase;

public class SimpleCacheTest extends TestCase {
	public void testPutGet () {
		SimpleCache c = new SimpleCache(Long.MAX_VALUE, new HashMap());
		c.put("key1", "value1");
		assertEquals("value1", c.get("key1"));
		c.put("key1", "value1.0");
		assertEquals("value1.0", c.get("key1"));
		c.put("key2", "value2");
		assertEquals("value2", c.get("key2"));
		assertEquals("value1.0", c.get("key1"));
	}
	
	public void testMaxAge () throws InterruptedException {
		SimpleCache c = new SimpleCache(1000, new HashMap());
		c.put("key1", "value1");
		assertEquals("value1", c.get("key1"));
		Thread.sleep(1500);
		assertNull(c.get("key1"));
		
		c.put("key2", "value2");
		Thread.sleep(750);
		c.put("key3", "value3");
		Thread.sleep(750);
		assertNull(c.get("key2"));
		assertNotNull(c.get("key3"));
		Thread.sleep(750);
		assertNull(c.get("key3"));
	}
	
	public void testRemove () {
		SimpleCache c = new SimpleCache(Long.MAX_VALUE, new HashMap());
		c.remove("key");
		assertNull(c.get("key"));
		c.put("key", "value");
		assertNotNull(c.get("key"));
		c.remove("key");
		assertNull(c.get("key"));
	}
	
	public void testCallBack () {
		SimpleCache c = new SimpleCache(Long.MAX_VALUE, new HashMap());
		assertEquals("value1", c.get("key1", new SimpleCache.Callback() {
			public Object execute() {
				return "value1";
			}
		}));
		assertEquals("value1", c.get("key1"));
		
		// again with a new callback (value)
		c.get("key1", new SimpleCache.Callback() {
			public Object execute() {
				return "value2";
			}
		});
		assertEquals("value1", c.get("key1"));
	}
}
Cache (computing)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How to Leverage Method Chaining To Add Smart Message Routing in Java
  • How to Hash, Salt, and Verify Passwords in NodeJS, Python, Golang, and Java
  • Querying Kafka Topics Using Presto
  • Application Scalability — How To Do Efficient Scaling

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo