如何在不传入任何键的情况下获取Guava LoadingCache的所有值
嘿,这个问题我之前做项目时也遇到过!Guava的LoadingCache确实没有直接提供“一键获取所有缓存值”的API,但有几个简单且靠谱的方案能满足你的需求,我给你详细说说:
方案一:利用
asMap()获取缓存视图 这是最直接的方法,LoadingCache继承自Cache,而Cache提供了asMap()方法,它会返回一个线程安全的Map视图,这个视图和原缓存实时同步——缓存里的内容变化,Map里也会跟着变,反过来修改Map也会影响缓存。
要获取所有缓存值的话,直接调用这个Map的values()方法就行:
// 假设你的缓存声明是这样的 LoadingCache<String, YourResultType> yourCache = CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .build(new CacheLoader<String, YourResultType>() { @Override public YourResultType load(String key) throws Exception { // 从数据源加载数据的逻辑 return fetchFromDataSource(key); } }); // 获取当前缓存中所有的值 Collection<YourResultType> allCachedValues = yourCache.asMap().values();
注意点:
- 这个Map视图的读取操作(比如遍历
values())不会触发缓存加载——也就是说,不会因为你遍历就自动去加载那些还没被缓存的键,完全只返回当前已经存在于缓存里的值,这点很适合你的需求。 - 如果你的缓存有自动过期、大小淘汰等策略,
values()拿到的只是当前时刻缓存中存活的内容,后续这些值可能会被自动回收。
方案二:包装缓存自定义追踪(适合特殊场景)
如果需要更精细的控制(比如想单独维护缓存项的集合,或者要做一些额外的统计),可以自己写一个包装类,在调用put和load方法时同步更新一个线程安全的集合。不过这种方式有点冗余,除非你有特殊需求,不然不如直接用asMap()方便。
举个简单的例子:
public class TrackedLoadingCache<K, V> { private final LoadingCache<K, V> delegate; private final ConcurrentMap<K, V> trackedEntries = new ConcurrentHashMap<>(); public TrackedLoadingCache(LoadingCache<K, V> delegate) { this.delegate = delegate; // 初始化已有的缓存项 trackedEntries.putAll(delegate.asMap()); } public V get(K key) throws ExecutionException { V value = delegate.get(key); trackedEntries.put(key, value); return value; } public void put(K key, V value) { delegate.put(key, value); trackedEntries.put(key, value); } public Collection<V> getAllValues() { return Collections.unmodifiableCollection(trackedEntries.values()); } }
不过要注意,这种方式需要处理缓存自动回收的情况(比如过期被淘汰的项),可能需要结合缓存的移除监听器(CacheBuilder.removalListener())来同步更新trackedEntries,不然会出现集合和实际缓存不一致的情况。
总的来说,方案一是最推荐的,既简单又符合Guava缓存的设计逻辑,完全能满足你获取当前所有缓存值的需求。
内容的提问来源于stack exchange,提问作者Nomad
相关产品推荐
相关产品推荐

