Java time-based map/cache with expiring keys [closed] Java time-based map/cache with expiring keys [closed] java java

Java time-based map/cache with expiring keys [closed]


Yes. Google Collections, or Guava as it is named now has something called MapMaker which can do exactly that.

ConcurrentMap<Key, Graph> graphs = new MapMaker()   .concurrencyLevel(4)   .softKeys()   .weakValues()   .maximumSize(10000)   .expiration(10, TimeUnit.MINUTES)   .makeComputingMap(       new Function<Key, Graph>() {         public Graph apply(Key key) {           return createExpensiveGraph(key);         }       });

Update:

As of guava 10.0 (released September 28, 2011) many of these MapMaker methods have been deprecated in favour of the new CacheBuilder:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()    .maximumSize(10000)    .expireAfterWrite(10, TimeUnit.MINUTES)    .build(        new CacheLoader<Key, Graph>() {          public Graph load(Key key) throws AnyException {            return createExpensiveGraph(key);          }        });


This is a sample implementation that i did for the same requirement and concurrency works well. Might be useful for someone.

import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;/** *  * @author Vivekananthan M * * @param <K> * @param <V> */public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {    private static final long serialVersionUID = 1L;    private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();    private long expiryInMillis = 1000;    private static final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");    public WeakConcurrentHashMap() {        initialize();    }    public WeakConcurrentHashMap(long expiryInMillis) {        this.expiryInMillis = expiryInMillis;        initialize();    }    void initialize() {        new CleanerThread().start();    }    @Override    public V put(K key, V value) {        Date date = new Date();        timeMap.put(key, date.getTime());        System.out.println("Inserting : " + sdf.format(date) + " : " + key + " : " + value);        V returnVal = super.put(key, value);        return returnVal;    }    @Override    public void putAll(Map<? extends K, ? extends V> m) {        for (K key : m.keySet()) {            put(key, m.get(key));        }    }    @Override    public V putIfAbsent(K key, V value) {        if (!containsKey(key))            return put(key, value);        else            return get(key);    }    class CleanerThread extends Thread {        @Override        public void run() {            System.out.println("Initiating Cleaner Thread..");            while (true) {                cleanMap();                try {                    Thread.sleep(expiryInMillis / 2);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }        private void cleanMap() {            long currentTime = new Date().getTime();            for (K key : timeMap.keySet()) {                if (currentTime > (timeMap.get(key) + expiryInMillis)) {                    V value = remove(key);                    timeMap.remove(key);                    System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);                }            }        }    }}


Git Repo Link (With Listener Implementation)

https://github.com/vivekjustthink/WeakConcurrentHashMap

Cheers!!


Apache Commons has decorator for Map to expire entries: PassiveExpiringMapIt's more simple than caches from Guava.

P.S. be careful, it's not synchronized.