Class Cache<K,V>
- Type Parameters:
K- The key type. Can be an array type for content-based key matching.V- The value type.
Overview:
This class uses ConcurrentHashMap internally to provide a thread-safe caching layer with automatic
value computation, cache eviction, and statistics tracking. It's designed for caching expensive-to-compute
or frequently-accessed objects to improve performance.
Features:
- Thread-safe concurrent access without external synchronization
- Automatic cache eviction when maximum size is reached
- Lazy computation via
Supplierpattern - Default supplier support for simplified access
- Built-in hit/miss statistics tracking
- Optional logging of cache statistics on JVM shutdown
- Can be disabled entirely via builder or system property
- Array Support: Arrays can be used as keys with proper content-based hashing and equality
Usage:
Array Support:
Unlike standard HashMap which uses identity-based equality for array keys,
this class properly handles arrays using content-based comparison:
Cache Behavior:
- When a key is requested:
- If the key exists in the cache, the cached value is returned (cache hit)
- If the key doesn't exist, the supplier is invoked to compute the value
- The computed value is stored in the cache and returned (cache miss)
- When the cache exceeds
Cache.Builder.maxSize(int), the entire cache is cleared - If the cache is disabled, the supplier is always invoked without caching
- Null keys always bypass the cache and invoke the supplier
Environment Variables:
The following system properties can be used to configure default cache behavior:
juneau.cache.mode - Cache mode: NONE/WEAK/FULL (default: FULL, case-insensitive)juneau.cache.maxSize - Maximum cache size before eviction (default: 1000)juneau.cache.logOnExit - Log cache statistics on shutdown (default:false )
Thread Safety:
This class is thread-safe and can be safely used from multiple threads without external synchronization. However, note that when the cache is cleared due to exceeding max size, there's a small window where multiple threads might compute the same value. This is acceptable for most use cases as it only affects performance, not correctness.
Performance Considerations:
- Cache operations are O(1) average time complexity
- The
get(Object, Supplier)method usesConcurrentHashMap.putIfAbsent(Object, Object)to minimize redundant computation in concurrent scenarios - When max size is exceeded, the entire cache is cleared in a single operation
- Statistics tracking uses
LongAdderfor thread-safe counting without locking - For arrays, content-based hashing via
Arrays.hashCode(Object[])ensures proper cache hits
Examples:
See Also:
-
Nested Class Summary
Nested Classes -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidcleanup()Cleans up thread-local storage for the current thread.voidclear()Removes all entries from the cache.booleancontainsKey(K key) Returnstrue if the cache contains a mapping for the specified key.booleancontainsValue(V value) Returnstrue if the cache contains one or more entries with the specified value.static <K,V> Cache.Builder<K, V> create()Creates a newCache.Builderfor constructing a cache with explicit type parameters.Retrieves a cached value by key using the default supplier.Retrieves a cached value by key, computing it if necessary using the provided supplier.intReturns the total number of cache hits since this cache was created.booleanisEmpty()Returnstrue if the cache contains no entries.static <K,V> Cache.Builder<K, V> Creates a newCache.Builderfor constructing a cache.Associates the specified value with the specified key in this cache.Removes the entry for the specified key from the cache.intsize()Returns the number of entries in the cache.
-
Constructor Details
-
Cache
Constructor.- Parameters:
builder- The builder containing configuration settings.
-
-
Method Details
-
create
Creates a newCache.Builderfor constructing a cache with explicit type parameters.This variant allows you to specify the cache's generic types explicitly without passing the class objects, which is useful when working with complex parameterized types.
Example:
// Working with complex generic types Cache<Class<?>,List<AnnotationInfo<Annotation>>>cache = Cache.<Class<?>,List<AnnotationInfo<Annotation>>>create () .supplier(key -> findAnnotations(key )) .build();- Type Parameters:
K- The key type.V- The value type.- Returns:
- A new builder for configuring the cache.
-
of
Creates a newCache.Builderfor constructing a cache.Example:
Cache<String,Pattern>
cache = Cache .of (String.class , Pattern.class ) .maxSize(100) .build();- Type Parameters:
K- The key type.V- The value type.- Parameters:
key- The key type class (used for type safety).type- The value type class.- Returns:
- A new builder for configuring the cache.
-
clear
Removes all entries from the cache. -
cleanup
Cleans up thread-local storage for the current thread.This method should be called when a thread is finished using this cache to prevent memory leaks in thread pool environments where threads are reused. Only has an effect if this cache was created with thread-local mode enabled.
-
containsKey
Returnstrue if the cache contains a mapping for the specified key.- Parameters:
key- The key to check. Can benull (null keys are supported like any other key).- Returns:
true if the cache contains the key.
-
containsValue
Returnstrue if the cache contains one or more entries with the specified value.- Parameters:
value- The value to check. Can benull , in which case this method returnsfalse (the cache never storesnull values).- Returns:
true if the cache contains the value.
-
get
Retrieves a cached value by key using the default supplier.This method uses the default supplier configured via
Cache.Builder.supplier(Function). If no default supplier was configured, this method will throw aNullPointerException.Example:
Cache<String,Pattern>
cache = Cache .of (String.class , Pattern.class ) .supplier(Pattern::compile) .build();// Uses default supplier Patternp =cache .get("[0-9]+" );- Parameters:
key- The cache key. Can benull (null keys are supported like any other key).- Returns:
- The cached or computed value. May be
null if the supplier returnsnull . - Throws:
NullPointerException- if no default supplier was configured.
-
get
Retrieves a cached value by key, computing it if necessary using the provided supplier.This method implements the cache-aside pattern:
- If the key exists in the cache, return the cached value (cache hit)
- If the key doesn't exist, invoke the supplier to compute the value
- Store the computed value in the cache using
ConcurrentHashMap.putIfAbsent(Object, Object) - Return the value
Behavior:
- If the cache is disabled, always invokes the supplier without caching
- If the cache exceeds
Cache.Builder.maxSize(int), clears all entries before storing the new value - Thread-safe: Multiple threads can safely call this method concurrently
- The supplier may be called multiple times for the same key in concurrent scenarios
(due to
ConcurrentHashMap.putIfAbsent(Object, Object)semantics) - Array Keys: Arrays are matched by content, not identity
Example:
Cache<String,Pattern>
cache = Cache.of (String.class , Pattern.class ).build();// First call: compiles pattern and caches it Patternp1 =cache .get("[0-9]+" , () -> Pattern.compile("[0-9]+" ));// Second call: returns cached pattern instantly Patternp2 =cache .get("[0-9]+" , () -> Pattern.compile("[0-9]+" ));assert p1 ==p2 ;// Same instance - Parameters:
key- The cache key. Can benull (null keys are supported like any other key).supplier- The supplier to compute the value if it's not in the cache. Must not benull or anIllegalArgumentExceptionis thrown.- Returns:
- The cached or computed value. May be
null if the supplier returnsnull .
-
getCacheHits
Returns the total number of cache hits since this cache was created.A cache hit occurs when
get(Object)orget(Object, Supplier)finds an existing cached value for the requested key, avoiding the need to invoke the supplier.Cache Effectiveness:
You can calculate the cache hit ratio using:
int hits =cache .getCacheHits();int misses =cache .size();int total =hits +misses ;double hitRatio = (double )hits /total ;// 0.0 to 1.0 Notes:
- Returns:
- The total number of cache hits since creation.
-
isEmpty
Returnstrue if the cache contains no entries.- Returns:
true if the cache is empty.
-
put
Associates the specified value with the specified key in this cache.- Parameters:
key- The cache key. Can benull (null keys are supported like any other key).value- The value to associate with the key.- Returns:
- The previous value associated with the key, or
null if there was no mapping.
-
remove
Removes the entry for the specified key from the cache.- Parameters:
key- The key to remove. Can benull (null keys are supported like any other key).- Returns:
- The previous value associated with the key, or
null if there was no mapping.
-
size
Returns the number of entries in the cache.- Returns:
- The number of cached entries.
-