This example Java source code file (CacheBuilder.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
/*
* 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.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.Equivalence;
import com.google.common.base.MoreObjects;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Ticker;
import com.google.common.cache.AbstractCache.SimpleStatsCounter;
import com.google.common.cache.AbstractCache.StatsCounter;
import com.google.common.cache.LocalCache.Strength;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ConcurrentModificationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckReturnValue;
/**
* <p>A builder of {@link LoadingCache} and {@link Cache} instances having any combination of the
* following features:
*
* <ul>
* <li>automatic loading of entries into the cache
* <li>least-recently-used eviction when a maximum size is exceeded
* <li>time-based expiration of entries, measured since last access or last write
* <li>keys automatically wrapped in {@linkplain WeakReference weak} references
* <li>values automatically wrapped in {@linkplain WeakReference weak} or {@linkplain SoftReference
* soft} references
* <li>notification of evicted (or otherwise removed) entries
* <li>accumulation of cache access statistics
* </ul>
*
*
* <p>These features are all optional; caches can be created using all or none of them. By default
* cache instances created by {@code CacheBuilder} will not perform any type of eviction.
*
* <p>Usage example:
{@code
*
* // 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);
* }
* });}</pre>
*
* <p>The returned cache is implemented as a hash table with similar performance characteristics to
* {@link ConcurrentHashMap}. It implements all optional operations of the {@link LoadingCache} and
* {@link Cache} interfaces. The {@code asMap} view (and its collection views) have <i>weakly
* consistent iterators</i>. 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
* {@link ConcurrentModificationException}.
*
* <p>Note: by default, the returned cache uses equality comparisons (the
* {@link Object#equals equals} method) to determine equality for keys or values. However, if
* {@link #weakKeys} was specified, the cache uses identity ({@code ==}) comparisons instead for
* keys. Likewise, if {@link #weakValues} or {@link #softValues} was specified, the cache uses
* identity comparisons for values.
*
* <p>Entries are automatically evicted from the cache when any of {@linkplain #maximumSize(long)
* maximumSize}, {@linkplain #maximumWeight(long) maximumWeight}, {@linkplain #expireAfterWrite
* expireAfterWrite}, {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys
* weakKeys}, {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} are
* requested.
*
* <p>If {@linkplain #maximumSize(long) maximumSize} or {@linkplain #maximumWeight(long)
* maximumWeight} is requested entries may be evicted on each cache modification.
*
* <p>If {@linkplain #expireAfterWrite expireAfterWrite} or {@linkplain #expireAfterAccess
* expireAfterAccess} is requested entries may be evicted on each cache modification, on occasional
* cache accesses, or on calls to {@link Cache#cleanUp}. Expired entries may be counted by
* {@link Cache#size}, but will never be visible to read or write operations.
*
* <p>If {@linkplain #weakKeys weakKeys}, {@linkplain #weakValues weakValues}, or
* {@linkplain #softValues 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
* {@link Cache#cleanUp}; such entries may be counted in {@link Cache#size}, but will never be
* visible to read or write operations.
*
* <p>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 {@link 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
* {@linkplain #removalListener removalListener}, {@linkplain #expireAfterWrite expireAfterWrite},
* {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys weakKeys},
* {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} perform periodic
* maintenance.
*
* <p>The caches produced by {@code CacheBuilder} are serializable, and the deserialized caches
* retain all the configuration properties of the original cache. Note that the serialized form does
* <i>not include cache contents, but only configuration.
*
* <p>See the Guava User Guide article on
* <a href="https://github.com/google/guava/wiki/CachesExplained">caching for a higher-level
* explanation.
*
* @param <K> the base key type for all caches created by this builder
* @param <V> the base value type for all caches created by this builder
* @author Charles Fry
* @author 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 StatsCounter> NULL_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 EMPTY_STATS;
}
});
static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0);
static final Supplier<StatsCounter> CACHE_STATS_COUNTER =
new Supplier<StatsCounter>() {
@Override
public StatsCounter get() {
return new SimpleStatsCounter();
}
};
enum NullListener implements RemovalListener<Object, Object> {
INSTANCE;
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {}
}
enum OneWeigher implements Weigher<Object, Object> {
INSTANCE;
@Override
public int weigh(Object key, Object 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;
int initialCapacity = UNSET_INT;
int concurrencyLevel = UNSET_INT;
long maximumSize = UNSET_INT;
long maximumWeight = UNSET_INT;
Weigher<? super K, ? super V> weigher;
Strength keyStrength;
Strength valueStrength;
long expireAfterWriteNanos = UNSET_INT;
long expireAfterAccessNanos = UNSET_INT;
long refreshNanos = UNSET_INT;
Equivalence<Object> keyEquivalence;
Equivalence<Object> valueEquivalence;
RemovalListener<? super K, ? super V> removalListener;
Ticker ticker;
Supplier<? extends StatsCounter> statsCounterSupplier = NULL_STATS_COUNTER;
// TODO(fry): make constructor private and update tests to use newBuilder
CacheBuilder() {}
/**
* Constructs a new {@code CacheBuilder} instance with default settings, including strong keys,
* strong values, and no automatic eviction of any kind.
*/
public static CacheBuilder<Object, Object> newBuilder() {
return new CacheBuilder<Object, Object>();
}
/**
* Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
*
* @since 12.0
*/
@GwtIncompatible // To be supported
public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
return spec.toCacheBuilder().lenientParsing();
}
/**
* Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
* This is especially useful for command-line configuration of a {@code CacheBuilder}.
*
* @param spec a String in the format specified by {@link CacheBuilderSpec}
* @since 12.0
*/
@GwtIncompatible // To be supported
public static CacheBuilder<Object, Object> from(String spec) {
return from(CacheBuilderSpec.parse(spec));
}
/**
* Enables lenient parsing. Useful for tests and spec parsing.
*
* @return this {@code CacheBuilder} instance (for chaining)
*/
@GwtIncompatible // To be supported
CacheBuilder<K, V> lenientParsing() {
strictParsing = false;
return this;
}
/**
* Sets a custom {@code Equivalence} strategy for comparing keys.
*
* <p>By default, the cache uses {@link Equivalence#identity} to determine key equality when
* {@link #weakKeys} is specified, and {@link Equivalence#equals()} otherwise.
*
* @return this {@code CacheBuilder} instance (for chaining)
*/
@GwtIncompatible // To be supported
CacheBuilder<K, V> keyEquivalence(Equivalence
Other Java examples (source code examples)
Here is a short list of links related to this Java CacheBuilder.java source code file: