如何使用条目自动过期实现CacheMap?

时间:2016-04-12 05:25:30

标签: java caching dictionary

大家好我想在java中实现缓存映射,其中映射条目在给定时间后到期。

我有这样的界面,我必须实现这些方法,但我不明白实际上是如何开始的。

    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;
    }

}

请告诉我如何实现这些方法,如何为我开始写一点代码,请用代码更新我的cachemap接口。

2 个答案:

答案 0 :(得分:2)

您必须使用相同的密钥管理内部地图。使用put方法将新值添加到地图中,并为内部时间映射添加值。您可以将Long存储为值,这是该值的具体时间。

然后,在后台启动一个新线程,它将检查内部地图中所有键的所有时间,并从内部地图和主地图中删除那些“旧”条目。

这是代码。我看到你的Map实现了一个接口,其中提供了一些清除过期值的方法,我知道你不需要一种自动方法来删除过期的值。所以,代码应该是这样的:

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();
    }

}

答案 1 :(得分:0)

怎么样

package map;

import java.util.Map;

import lombok.Getter;

public class TimeOutCacheMap<K, V> {



Long timeout;

    @Getter
    private static class MapValue<V> {
        private Long timeOut;
        private V v;

        public MapValue(Long timeout, V v) {
            this.timeOut = timeout;
            this.v = v;
        }
    }

    public TimeOutCacheMap(Long timeoutInMilliSeconds, Class<? extends Map> mapClazz) {
        if (timeoutInMilliSeconds > 5000000) {
            throw new RuntimeException("Timeout can be upto 5000000");
        }
        this.timeout = timeoutInMilliSeconds;
        try {
            map = mapClazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Map<K, MapValue<V>> map;


    public V put(K k, V v) {
        if (k == null) {
            throw new RuntimeException("Invalid key");
        }
        Long currentTime = System.currentTimeMillis();
        Long timeOutValue = currentTime + this.timeout;
        MapValue<V> newV = new MapValue<V>(timeOutValue, v);
        MapValue<V> oldV = map.put(k, newV);
        return ((oldV == null) ? null : oldV.getV());
    }

    public V get(K k) {
        if (k == null) {
            throw new RuntimeException("Invalid key");
        }
        Long currentTime = System.currentTimeMillis();
        MapValue<V> mapValue = map.get(k);
        if (mapValue!=null &&  mapValue.getTimeOut() != null && mapValue.getTimeOut() >= currentTime) {
            return mapValue.getV();
        } else {
            map.remove(k);
            return null;
        }
    }
}