Search code examples
javacachingdictionary

How to Implement CacheMap with automatic expiration of entries?


Hi everyone I want to implement cache map in java in which map entries expire after given time.

I have interface like this, I have to implement these methods, but I am not understand how actually start.

    public class CacheMapImpl implements CacheMap<Integer, String> {

    @Override
    public void setTimeToLive(long timeToLive) {


    }

    @Override
    public long getTimeToLive() {

        return 0;
    }

    @Override
    public String put(Integer key, String value) {

        return null;
    }

    @Override
    public void clearExpired() {


    }

    @Override
    public void clear() {


    }

    @Override
    public boolean containsKey(Object key) {

        return false;
    }

    @Override
    public boolean containsValue(Object value) {

        return false;
    }

    @Override
    public String get(Object key) {

        return null;
    }

    @Override
    public boolean isEmpty() {

        return false;
    }

    @Override
    public String remove(Object key) {

        return null;
    }

    @Override
    public int size() {

        return 0;
    }

}

Please tell me how to implement these methods, how to start write little bit code for me, kindly update my cachemap interface with code.


Solution

  • You have to manage an internal map with the same key. Use your put method to add the new value to your map and also add a value for your internal times' map. You can store a Long as a value, which is the concrete time for that value.

    Then, start a new thread in the background that will check all times for all keys in the internal map and remove those that are 'old' entries from both, internal map and your main map.

    Here is the code. As I see your Map implements an interface with some methods provided to clear the expired values, I understand you don't need an automatic way to remove expired values. So, the code should be something like:

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class CacheMapImpl implements CacheMap<Integer, String> {
    
        private Map<Integer, Long> timesCache = new HashMap<Integer, Long>();
        private Map<Integer, String> values = new HashMap<Integer, String>();
    
        /** Time for the elemens to keep alive in the map in milliseconds. */
        long timeToLive = 0;
    
        @Override
        public void setTimeToLive(long timeToLive) {
            this.timeToLive = timeToLive;
        }
    
        @Override
        public long getTimeToLive() {
    
            return this.timeToLive;
        }
    
        @Override
        public String put(Integer key, String value) {
            values.put(key, value);
            timesCache.put(key, System.currentTimeMillis());
            return value;
        }
    
        @Override
        public void clearExpired() {
            
            // Just remove if timeToLive has been set before...
            if (timeToLive > 0) {
                List<Integer> keysToClear = new ArrayList<Integer>();
                long currentTime = System.currentTimeMillis();
                
                // Check what keys to remove
                for (Entry<Integer, Long> e : timesCache.entrySet()) {
                    if ((currentTime - e.getValue().longValue()) > this.timeToLive) {
                        keysToClear.add(e.getKey());
                    }
                }
                
                // Remove the expired keys
                for (Integer key : keysToClear) {
                    this.timesCache.remove(key);
                    this.values.remove(key);
                }
            }
    
        }
    
        @Override
        public void clear() {
            this.timesCache.clear();
            this.values.clear();
        }
    
        @Override
        public boolean containsKey(Object key) {
    
            return this.values.containsKey(key);
        }
    
        @Override
        public boolean containsValue(Object value) {
    
            return this.values.containsValue(value);
        }
    
        @Override
        public String get(Object key) {
    
            return this.values.get(key);
        }
    
        @Override
        public boolean isEmpty() {
    
            return this.values.isEmpty();
        }
    
        @Override
        public String remove(Object key) {
            String rto = null;
            if (containsKey(key)) {
                this.values.remove(key);
                this.timesCache.remove(key);
                rto = key.toString();
            }
            return rto;
        }
    
        @Override
        public int size() {
    
            return this.values.size();
        }
    
    }