package com.qxs.business.reform.utils;
import java.util.*;
/**
* 超时Map,模拟redis超时
*/
public class ExpiryMap<K, V> extends HashMap<K, V> {
private long EXPIRY = 1000*60*60*6;// 默认缓存超时时间 6小时
private static ExpiryMap<String, Object> dataMap;
private HashMap<K, Long> timeMap = new HashMap<>();// 存储过期时间
private int num = 0;// 一个计数器
private ExpiryMap() {}// 构造器私有化
// 采用单例模式获取实例
public static ExpiryMap getInstance() {
if (null == dataMap) {
dataMap = new ExpiryMap<>();
}
return dataMap;
}
@Override
public V put(K key, V value) {
timeMap.put(key, System.currentTimeMillis() + EXPIRY);
return super.put(key, value);
}
public V put(K key, V value, long expiryTime) {
timeMap.put(key, System.currentTimeMillis() + expiryTime);
return super.put(key, value);
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
timeMap.put(e.getKey(), System.currentTimeMillis() + EXPIRY);
}
super.putAll(m);
}
public void putAll(Map<? extends K, ? extends V> m, long expiryTime) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
timeMap.put(e.getKey(), System.currentTimeMillis() + expiryTime);
}
super.putAll(m);
}
@Override
public V get(Object key) {
if (key == null) {
return null;
}
if(checkExpiry(key, true)) {
return null;
}
return super.get(key);
}
@Override
public V remove(Object key) {
timeMap.remove(key);
return super.remove(key);
}
@Override
public void clear() {
timeMap.clear();
super.clear();
}
@Override
public boolean containsKey(Object key) {
num++;
if (num > 100) {
num = 0;
delAllExpiry();// 每调用该方法100次,检测一下所有已经过期的key,进行删除
}
return !checkExpiry(key, true) && super.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
if (value == null) {
return Boolean.FALSE;
}
Boolean flag = Boolean.FALSE;
Set<Entry<K, V>> entries = super.entrySet();
List<Object> rm = new ArrayList<>();
for (Entry<K, V> entry : entries) {
Boolean bool = checkExpiry(entry.getKey(), false);
if (bool)
rm.add(entry.getKey());
// value相等,并且key没有过期
if (value.equals(entry.getValue()) && !bool) {
flag = Boolean.TRUE;
break;
}
}
for (Object key : rm) {
timeMap.remove(key);
super.remove(key);
}
return flag;
}
@Override
public Collection<V> values() {
delAllExpiry();
return super.values();
}
/**
* 是否过期 true代表已过期
* @return
*/
private boolean checkExpiry(Object key, boolean isRemove){
if(!timeMap.containsKey(key)){
return Boolean.TRUE;// 没有,代表已过期
}
long expiryTime = timeMap.get(key);
boolean flag = System.currentTimeMillis() > expiryTime;
if(flag && isRemove){
super.remove(key);
timeMap.remove(key);
}
return flag;
}
// 删除所有已过期的key
private void delAllExpiry() {
Set<K> keySet = super.keySet();
List<Object> rm = new ArrayList<>();
for (K key : keySet) {
Boolean bool = checkExpiry(key, false);
if (bool)
rm.add(key);
}
for (Object key : rm) {
timeMap.remove(key);
super.remove(key);
}
}
}
参考:https://blog.csdn.net/qq_16504067/article/details/125788162