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")); } }
class Array def swap!(a,b) self[a], self[b] = self[b], self[a] self end end You can now do stuff like.. [1,2,3,4].swap!(2,3) # = [1,2,4,3] etc.. Many thanks to Sam Stephenson and technoweenie for their suggestions.