为什么Cache.asMap()与Cache.size()不一致?

在Guava库中,我很困惑为什么Cache.asMap()Cache.size()不一致,除非Cache.cleanUp()

 Cache cache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.SECONDS) .build(); cache.get(...); ... //After some seconds, all entries are expired. //cache.asMap() is EMPTY Map, but cache.size() != 0 

所以我的问题是: Cache.asMap()Cache.size()不一致是错误吗? 虽然我注意到Cache.size()的javadoc是:

  /** * Returns the **approximate** number of entries in this cache. */ 

我猜它可能与并发环境有关。 而Cache.cleanUp()究竟做了什么?

Guava的缓存是围绕锁定摊销设计的,而cleanUp方法则强制缓存达到一致状态。 Map.size()方法是近似值,但可以计算由于到期或参考驱逐而等待删除的条目。 Guava高速缓存中近似值的可见性对于应用程序来说很少有用,它倾向于将高速缓存视为瞬态数据存储。 来自Map的缓存的不同期望导致asMap方法允许将缓存视为地图,但不喜欢开发人员以这种方式感知它。

StrangleLoop 2011会议幻灯片介绍了缓存的实现细节。 来自Guava缓存的ConcurrentLinkedHashMap的设计文档也可能引起关注,但描述的方法略有不同。

Ben给出了很好的高层回应。 低级别的回应是:

asMap()视图可以遍历缓存中的每个元素,因此可以跳过待处理清除的无效条目。 另一方面, size()预计是一个快速操作,遍历整个缓存只是为了获得更准确的大小估计是愚蠢的。

CacheBuilder javadocs详细介绍了在各种情况下需要进行的清理(例如expireAfterWrite ,在您的情况下)。