Why is Cache.asMap() not consistent with Cache.size()?

caching, concurrency, guava, java

Solution

Guava's cache is designed around lock amortization and the `cleanUp` method forces the cache to arrive at a consistent state. The `Map.size()` method is an approximation, but may count entries pending removal due to expiration or reference eviction. The visibility of the approximations in Guava's cache are rarely of much interest to an application, which tends to think of a cache as a transient data store. The different expectations of a cache from a Map led to the `asMap` method to allow the cache to be viewed as a map, but disfavor developers perceiving it that way.

The implementation details of the cache was covered in the StrangleLoop 2011 conference slides. The design document of `ConcurrentLinkedHashMap`, which Guava's cache was derived from, may also be of interest but describes a slightly different approach.

Problem

In the Guava Library, I am confused about why `Cache.asMap()` is not consistent with `Cache.size()`, unless `Cache.cleanUp()` is called. ``` Cache<Object, Object> 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 ``` So my question: Is it bug that `Cache.asMap()` is not consistent to `Cache.size()`? Although I notice the javadoc of `Cache.size()` is: ``` /** * Returns the **approximate** number of entries in this cache. */ ``` I can just guess it's related to a concurrent environment. And what does `Cache.cleanUp()` do exactly?

Original source