Java中可用泛型+ConcurrentHashMap实现轻量缓存框架,支持键值类型可变、过期判断与自动清理;核心类SimpleCache封装put/get/containsKey等操作,CacheEntry记录创建时间并提供isExpired判断,使用示例展示String→User缓存及自定义过期策略。

Java 中可以用泛型 + HashMap 快速实现一个线程不安全但轻量的缓存框架,核心是封装「键类型可变、值类型可变、支持过期判断(简易版)」的能力。下面是一个实用、易理解、可直接上手的实现方案。
1. 定义带过期时间的缓存项(CacheEntry)
缓存不能只存值,还要记录创建时间,便于后续判断是否过期。用泛型封装键和值类型,并内嵌有效期逻辑:
public class CacheEntry<v> {
private final V value;
private final long createTime;
private final long expireAfterMillis;
<pre class="brush:php;toolbar:false;">public CacheEntry(V value, long expireAfterMillis) {
this.value = value;
this.createTime = System.currentTimeMillis();
this.expireAfterMillis = expireAfterMillis;
}
public V getValue() {
return value;
}
public boolean isExpired() {
return System.currentTimeMillis() - createTime > expireAfterMillis;
}
}
2. 泛型缓存类(SimpleCache)
主类使用 ConcurrentHashMap(比 HashMap 更适合多线程场景,且线程安全),支持泛型键(K)和值(V),提供基本的存、取、删、清空操作:
import java.util.concurrent.ConcurrentHashMap;
<p>public class SimpleCache<k v> {
private final ConcurrentHashMap<k cacheentry>> cacheMap;
private final long defaultExpireMillis;</k></k></p><pre class="brush:php;toolbar:false;">public SimpleCache() {
this(0); // 永不过期
}
public SimpleCache(long defaultExpireMillis) {
this.cacheMap = new ConcurrentHashMap();
this.defaultExpireMillis = defaultExpireMillis;
}
public void put(K key, V value) {
put(key, value, defaultExpireMillis);
}
public void put(K key, V value, long expireAfterMillis) {
cacheMap.put(key, new CacheEntry(value, expireAfterMillis));
}
public V get(K key) {
CacheEntry<v> entry = cacheMap.get(key);
if (entry == null || entry.isExpired()) {
cacheMap.remove(key); // 自动清理过期项(惰性)
return null;
}
return entry.getValue();
}
public boolean containsKey(K key) {
CacheEntry<v> entry = cacheMap.get(key);
return entry != null && !entry.isExpired();
}
public void remove(K key) {
cacheMap.remove(key);
}
public void clear() {
cacheMap.clear();
}
public int size() {
return cacheMap.size();
}</v></v>}
3. 使用示例(字符串 ID → 用户对象缓存)
泛型让缓存复用性极强,比如缓存用户、配置、API 响应等:
// 创建缓存:key 是 String,value 是 User,5 秒后自动过期
SimpleCache<string user> userCache = new SimpleCache(5_000);
<p>// 存入
userCache.put("u1001", new User("Alice", 28), 10_000); // 单独设 10 秒</p>
<p>// 获取(命中则返回,过期或不存在则返回 null)
User user = userCache.get("u1001");</p>
<p>// 判断是否存在(含过期检查)
if (userCache.containsKey("u1001")) {
System.out.println("缓存有效");
}</p></string>4. 注意事项与改进方向
这个实现轻量实用,但生产环境需注意以下几点:
-
线程安全:用了
ConcurrentHashMap,get/put 是线程安全的;但「判断过期 + 删除」不是原子操作,高并发下可能有极小概率返回已过期值(通常可接受) -
无定时清理:过期项靠 get 时惰性删除,若长期不访问会导致内存泄漏;如需主动清理,可加一个后台线程定期扫描(或改用
Caffeine等成熟库) -
无大小限制:缓存无限增长,可扩展 LRU 逻辑(例如用
LinkedHashMap+removeEldestEntry),或集成guava-cache/Caffeine - 泛型擦除不影响功能:运行时类型信息虽被擦除,但编译期类型安全已由泛型保障,无需额外处理
不复杂但容易忽略:缓存的核心不是“存”,而是“何时不返回旧数据”。加上时间维度和泛型封装,就已具备实用缓存的骨架。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











