Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2009 The Guava Authors
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package com.google.common.cache;
 
 import static com.google.common.base.Objects.firstNonNull;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
 
 

A builder of com.google.common.cache.LoadingCache and com.google.common.cache.Cache instances having any combination of the following features:

  • automatic loading of entries into the cache
  • least-recently-used eviction when a maximum size is exceeded
  • time-based expiration of entries, measured since last access or last write
  • keys automatically wrapped in weak references
  • values automatically wrapped in weak or soft references
  • notification of evicted (or otherwise removed) entries
  • accumulation of cache access statistics

These features are all optional; caches can be created using all or none of them. By default cache instances created by CacheBuilder will not perform any type of eviction.

Usage example:

   LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumSize(10000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .removalListener(MY_LISTENER)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             
           });}

Or equivalently,

   // In real life this would come from a command-line flag or config file
   String spec = "maximumSize=10000,expireAfterWrite=10m";

   LoadingCache<Key, Graph> graphs = CacheBuilder.from(spec)
       .removalListener(MY_LISTENER)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             
           });}

The returned cache is implemented as a hash table with similar performance characteristics to ConcurrentHashMap. It implements all optional operations of the com.google.common.cache.LoadingCache and com.google.common.cache.Cache interfaces. The asMap view (and its collection views) have weakly consistent iterators. This means that they are safe for concurrent use, but if other threads modify the cache after the iterator is created, it is undefined which of these changes, if any, are reflected in that iterator. These iterators never throw ConcurrentModificationException.

Note: by default, the returned cache uses equality comparisons (the equals method) to determine equality for keys or values. However, if weakKeys was specified, the cache uses identity (==) comparisons instead for keys. Likewise, if weakValues or softValues was specified, the cache uses identity comparisons for values.

Entries are automatically evicted from the cache when any of maximumSize, maximumWeight, expireAfterWrite, expireAfterAccess, weakKeys, weakValues, or softValues are requested.

If maximumSize or maximumWeight is requested entries may be evicted on each cache modification.

If expireAfterWrite or expireAfterAccess is requested entries may be evicted on each cache modification, on occasional cache accesses, or on calls to com.google.common.cache.Cache.cleanUp(). Expired entries may be counted by com.google.common.cache.Cache.size(), but will never be visible to read or write operations.

If weakKeys, weakValues, or softValues are requested, it is possible for a key or value present in the cache to be reclaimed by the garbage collector. Entries with reclaimed keys or values may be removed from the cache on each cache modification, on occasional cache accesses, or on calls to com.google.common.cache.Cache.cleanUp(); such entries may be counted in com.google.common.cache.Cache.size(), but will never be visible to read or write operations.

Certain cache configurations will result in the accrual of periodic maintenance tasks which will be performed during write operations, or during occasional read operations in the absence of writes. The com.google.common.cache.Cache.cleanUp() method of the returned cache will also perform maintenance, but calling it should not be necessary with a high throughput cache. Only caches built with removalListener, expireAfterWrite, expireAfterAccess, weakKeys, weakValues, or softValues perform periodic maintenance.

The caches produced by CacheBuilder are serializable, and the deserialized caches retain all the configuration properties of the original cache. Note that the serialized form does not include cache contents, but only configuration.

See the Guava User Guide article on caching for a higher-level explanation.

Parameters:
<K> the base key type for all caches created by this builder
<V> the base value type for all caches created by this builder
Author(s):
Charles Fry
Kevin Bourrillion
Since:
10.0
@GwtCompatible(emulated = true)
public final class CacheBuilder<K, V> {
  private static final int DEFAULT_INITIAL_CAPACITY = 16;
  private static final int DEFAULT_CONCURRENCY_LEVEL = 4;
  private static final int DEFAULT_EXPIRATION_NANOS = 0;
  private static final int DEFAULT_REFRESH_NANOS = 0;
  static final Supplier<? extends StatsCounterNULL_STATS_COUNTER = Suppliers.ofInstance(
      new StatsCounter() {
        @Override
        public void recordHits(int count) {}
        @Override
        public void recordMisses(int count) {}
        @Override
        public void recordLoadSuccess(long loadTime) {}
        @Override
        public void recordLoadException(long loadTime) {}
        @Override
        public void recordEviction() {}
        @Override
        public CacheStats snapshot() {
          return ;
        }
      });
  static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0);
      new Supplier<StatsCounter>() {
    @Override
    public StatsCounter get() {
      return new SimpleStatsCounter();
    }
  };
  enum NullListener implements RemovalListener<ObjectObject> {
    INSTANCE;
    @Override
    public void onRemoval(RemovalNotification<ObjectObjectnotification) {}
  }
  enum OneWeigher implements Weigher<ObjectObject> {
    INSTANCE;
    @Override
    public int weigh(Object keyObject value) {
      return 1;
    }
  }
  static final Ticker NULL_TICKER = new Ticker() {
    @Override
    public long read() {
      return 0;
    }
  };
  private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName());
  static final int UNSET_INT = -1;
  boolean strictParsing = true;
  long maximumSize = ;
  Weigher<? super K, ? super V> weigher;
  long refreshNanos = ;
  RemovalListener<? super K, ? super V> removalListener;
  // TODO(fry): make constructor private and update tests to use newBuilder
  CacheBuilder() {}

  
Constructs a new CacheBuilder instance with default settings, including strong keys, strong values, and no automatic eviction of any kind.
  public static CacheBuilder<ObjectObjectnewBuilder() {
    return new CacheBuilder<ObjectObject>();
  }
  }
  }

  
Sets the minimum total size for the internal hash tables. For example, if the initial capacity is 60, and the concurrency level is 8, then eight segments are created, each having a hash table of size eight. Providing a large enough estimate at construction time avoids the need for expensive resizing operations later, but setting this value unnecessarily high wastes memory.

Throws:
java.lang.IllegalArgumentException if initialCapacity is negative
java.lang.IllegalStateException if an initial capacity was already set
  public CacheBuilder<K, V> initialCapacity(int initialCapacity) {
    checkState(this. == "initial capacity was already set to %s",
        this.);
    checkArgument(initialCapacity >= 0);
    this. = initialCapacity;
    return this;
  }
  int getInitialCapacity() {
  }

  
Guides the allowed concurrency among update operations. Used as a hint for internal sizing. The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. Because assignment of entries to these partitions is not necessarily uniform, the actual concurrency observed may vary. Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table. Using a significantly higher value than you need can waste space and time, and a significantly lower value can lead to thread contention. But overestimates and underestimates within an order of magnitude do not usually have much noticeable impact. A value of one permits only one thread to modify the cache at a time, but since read operations and cache loading computations can proceed concurrently, this still yields higher concurrency than full synchronization.

Defaults to 4. Note:The default may change in the future. If you care about this value, you should always choose it explicitly.

The current implementation uses the concurrency level to create a fixed number of hashtable segments, each governed by its own write lock. The segment lock is taken once for each explicit write, and twice for each cache loading computation (once prior to loading the new value, and once after loading completes). Much internal cache management is performed at the segment granularity. For example, access queues and write queues are kept per segment when they are required by the selected eviction algorithm. As such, when writing unit tests it is not uncommon to specify concurrencyLevel(1) in order to achieve more deterministic eviction behavior.

Note that future implementations may abandon segment locking in favor of more advanced concurrency controls.

Throws:
java.lang.IllegalArgumentException if concurrencyLevel is nonpositive
java.lang.IllegalStateException if a concurrency level was already set
  public CacheBuilder<K, V> concurrencyLevel(int concurrencyLevel) {
    checkState(this. == "concurrency level was already set to %s",
        this.);
    checkArgument(concurrencyLevel > 0);
    this. = concurrencyLevel;
    return this;
  }
  }

  
Specifies the maximum number of entries the cache may contain. Note that the cache may evict an entry before this limit is exceeded. As the cache size grows close to the maximum, the cache evicts entries that are less likely to be used again. For example, the cache may evict an entry because it hasn't been used recently or very often.

When size is zero, elements will be evicted immediately after being loaded into the cache. This can be useful in testing, or to disable caching temporarily without a code change.

This feature cannot be used in conjunction with maximumWeight.

Parameters:
size the maximum size of the cache
Throws:
java.lang.IllegalArgumentException if size is negative
java.lang.IllegalStateException if a maximum size or weight was already set
  public CacheBuilder<K, V> maximumSize(long size) {
    checkState(this. == "maximum size was already set to %s",
        this.);
    checkState(this. == "maximum weight was already set to %s",
        this.);
    checkState(this. == null"maximum size can not be combined with weigher");
    checkArgument(size >= 0, "maximum size must not be negative");
    this. = size;
    return this;
  }
  long getMaximumWeight() {
    if ( == 0 ||  == 0) {
      return 0;
    }
    return ( == null) ?  : ;
  }
  // Make a safe contravariant cast now so we don't have to do it over and over.
  @SuppressWarnings("unchecked")
  <K1 extends K, V1 extends V> Weigher<K1, V1> getWeigher() {
    return (Weigher<K1, V1>) Objects.firstNonNull(.);
  }
  CacheBuilder<K, V> setKeyStrength(Strength strength) {
    checkState( == null"Key strength was already set to %s");
     = checkNotNull(strength);
    return this;
  }
  }
  CacheBuilder<K, V> setValueStrength(Strength strength) {
    checkState( == null"Value strength was already set to %s");
     = checkNotNull(strength);
    return this;
  }
  }

  
Specifies that each entry should be automatically removed from the cache once a fixed duration has elapsed after the entry's creation, or the most recent replacement of its value.

When duration is zero, this method hands off to maximumSize(0), ignoring any otherwise-specificed maximum size or weight. This can be useful in testing, or to disable caching temporarily without a code change.

Expired entries may be counted in com.google.common.cache.Cache.size(), but will never be visible to read or write operations. Expired entries are cleaned up as part of the routine maintenance described in the class javadoc.

Parameters:
duration the length of time after an entry is created that it should be automatically removed
unit the unit that duration is expressed in
Throws:
java.lang.IllegalArgumentException if duration is negative
java.lang.IllegalStateException if the time to live or time to idle was already set
  public CacheBuilder<K, V> expireAfterWrite(long durationTimeUnit unit) {
    checkState( == "expireAfterWrite was already set to %s ns",
        );
    checkArgument(duration >= 0, "duration cannot be negative: %s %s"durationunit);
    this. = unit.toNanos(duration);
    return this;
  }
  }

  
Specifies that each entry should be automatically removed from the cache once a fixed duration has elapsed after the entry's creation, the most recent replacement of its value, or its last access. Access time is reset by all cache read and write operations (including Cache.asMap().get(Object) and Cache.asMap().put(K, V)), but not by operations on the collection-views of com.google.common.cache.Cache.asMap().

When duration is zero, this method hands off to maximumSize(0), ignoring any otherwise-specificed maximum size or weight. This can be useful in testing, or to disable caching temporarily without a code change.

Expired entries may be counted in com.google.common.cache.Cache.size(), but will never be visible to read or write operations. Expired entries are cleaned up as part of the routine maintenance described in the class javadoc.

Parameters:
duration the length of time after an entry is last accessed that it should be automatically removed
unit the unit that duration is expressed in
Throws:
java.lang.IllegalArgumentException if duration is negative
java.lang.IllegalStateException if the time to idle or time to live was already set
  public CacheBuilder<K, V> expireAfterAccess(long durationTimeUnit unit) {
    checkState( == "expireAfterAccess was already set to %s ns",
        );
    checkArgument(duration >= 0, "duration cannot be negative: %s %s"durationunit);
    this. = unit.toNanos(duration);
    return this;
  }
    return ( == )
  }
  long getRefreshNanos() {
  }

  
Specifies a nanosecond-precision time source for use in determining when entries should be expired. By default, java.lang.System.nanoTime() is used.

The primary intent of this method is to facilitate testing of caches which have been configured with expireAfterWrite(long,java.util.concurrent.TimeUnit) or expireAfterAccess(long,java.util.concurrent.TimeUnit).

Throws:
java.lang.IllegalStateException if a ticker was already set
  public CacheBuilder<K, V> ticker(Ticker ticker) {
    checkState(this. == null);
    this. = checkNotNull(ticker);
    return this;
  }
  Ticker getTicker(boolean recordsTime) {
    if ( != null) {
      return ;
    }
    return recordsTime ? Ticker.systemTicker() : ;
  }

  
Specifies a listener instance that caches should notify each time an entry is removed for any reason. Each cache created by this builder will invoke this listener as part of the routine maintenance described in the class documentation above.

Warning: after invoking this method, do not continue to use this cache builder reference; instead use the reference this method returns. At runtime, these point to the same instance, but only the returned reference has the correct generic type information so as to ensure type safety. For best results, use the standard method-chaining idiom illustrated in the class documentation above, configuring a builder and building your cache in a single statement. Failure to heed this advice can result in a java.lang.ClassCastException being thrown by a cache operation at some undefined point in the future.

Warning: any exception thrown by listener will not be propagated to the Cache user, only logged via a java.util.logging.Logger.

Returns:
the cache builder reference that should be used instead of this for any remaining configuration and cache building
Throws:
java.lang.IllegalStateException if a removal listener was already set
  public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(
      RemovalListener<? super K1, ? super V1> listener) {
    checkState(this. == null);
    // safely limiting the kinds of caches this can produce
    @SuppressWarnings("unchecked")
    CacheBuilder<K1, V1> me = (CacheBuilder<K1, V1>) this;
    me.removalListener = checkNotNull(listener);
    return me;
  }
  // Make a safe contravariant cast now so we don't have to do it over and over.
  @SuppressWarnings("unchecked")
  <K1 extends K, V1 extends V> RemovalListener<K1, V1> getRemovalListener() {
    return (RemovalListener<K1, V1>) Objects.firstNonNull(.);
  }

  
Enable the accumulation of com.google.common.cache.CacheStats during the operation of the cache. Without this com.google.common.cache.Cache.stats() will return zero for all statistics. Note that recording stats requires bookkeeping to be performed with each operation, and thus imposes a performance penalty on cache operation.

Since:
12.0 (previously, stats collection was automatic)
  public CacheBuilder<K, V> recordStats() {
    return this;
  }
  
  boolean isRecordingStats() {
  }
    return ;
  }

  
Builds a cache, which either returns an already-loaded value for a given key or atomically computes or retrieves it using the supplied CacheLoader. If another thread is currently loading the value for this key, simply waits for that thread to finish and returns its loaded value. Note that multiple threads can concurrently load values for distinct keys.

This method does not alter the state of this CacheBuilder instance, so it can be invoked again to create multiple independent caches.

Parameters:
loader the cache loader used to obtain new values
Returns:
a cache having the requested features
  public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
      CacheLoader<? super K1, V1> loader) {
    return new LocalCache.LocalLoadingCache<K1, V1>(thisloader);
  }

  
Builds a cache which does not automatically load values when keys are requested.

Consider build(com.google.common.cache.CacheLoader) instead, if it is feasible to implement a CacheLoader.

This method does not alter the state of this CacheBuilder instance, so it can be invoked again to create multiple independent caches.

Returns:
a cache having the requested features
Since:
11.0
  public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
    return new LocalCache.LocalManualCache<K1, V1>(this);
  }
  private void checkNonLoadingCache() {
    checkState( == "refreshAfterWrite requires a LoadingCache");
  }
  private void checkWeightWithWeigher() {
    if ( == null) {
      checkState( == "maximumWeight requires weigher");
    } else {
      if () {
        checkState( != "weigher requires maximumWeight");
      } else {
        if ( == ) {
          .log(."ignoring weigher specified without maximumWeight");
        }
      }
    }
  }

  
Returns a string representation for this CacheBuilder instance. The exact form of the returned string is not specified.
  public String toString() {
    Objects.ToStringHelper s = Objects.toStringHelper(this);
    if ( != ) {
      s.add("initialCapacity");
    }
    if ( != ) {
      s.add("concurrencyLevel");
    }
    if ( != ) {
      s.add("maximumSize");
    }
    if ( != ) {
      s.add("maximumWeight");
    }
    if ( != ) {
      s.add("expireAfterWrite" + "ns");
    }
    if ( != ) {
      s.add("expireAfterAccess" + "ns");
    }
    if ( != null) {
      s.add("keyStrength", Ascii.toLowerCase(.toString()));
    }
    if ( != null) {
      s.add("valueStrength", Ascii.toLowerCase(.toString()));
    }
    if ( != null) {
      s.addValue("keyEquivalence");
    }
    if ( != null) {
      s.addValue("valueEquivalence");
    }
    if ( != null) {
      s.addValue("removalListener");
    }
    return s.toString();
  }
New to GrepCode? Check out our FAQ X