CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-ben-manes-caffeine--caffeine

A high performance caching library for Java providing Google Guava-inspired API with advanced eviction policies and comprehensive features

Pending
Overview
Eval results
Files

cache-construction.mddocs/

Cache Construction

The Caffeine builder provides a comprehensive fluent API for configuring cache instances. The builder pattern allows combining multiple configuration options and terminates with methods that create the actual cache instances.

Builder Factory Methods

public static Caffeine<Object, Object> newBuilder()
public static Caffeine<Object, Object> from(CaffeineSpec spec)
public static Caffeine<Object, Object> from(String spec)

Usage Example

// Basic builder creation
Caffeine<Object, Object> builder = Caffeine.newBuilder();

// From specification string
Caffeine<Object, Object> builder2 = Caffeine.from("maximumSize=10000,expireAfterWrite=10m");

// From specification object
CaffeineSpec spec = CaffeineSpec.parse("maximumSize=10000,expireAfterWrite=10m");
Caffeine<Object, Object> builder3 = Caffeine.from(spec);

Size and Weight Configuration

Configure cache capacity using either entry count or custom weights.

public Caffeine<K, V> initialCapacity(int initialCapacity)
public Caffeine<K, V> maximumSize(long maximumSize)
public Caffeine<K, V> maximumWeight(long maximumWeight)
public <K1, V1> Caffeine<K1, V1> weigher(Weigher<? super K1, ? super V1> weigher)

Usage Example

// Size-based eviction
Cache<String, String> sizeCache = Caffeine.newBuilder()
    .initialCapacity(100)
    .maximumSize(10_000)
    .build();

// Weight-based eviction with custom weigher
Cache<String, String> weightCache = Caffeine.newBuilder()
    .maximumWeight(100_000)
    .weigher((key, value) -> key.length() + value.length())
    .build();

Constraints: Cannot use both maximumSize() and maximumWeight() on the same builder.

Reference Strength Configuration

Configure memory management behavior for keys and values.

public Caffeine<K, V> weakKeys()
public Caffeine<K, V> weakValues()
public Caffeine<K, V> softValues()

Usage Example

// Weak references for keys (allows GC when no other references exist)
Cache<String, String> weakKeyCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .weakKeys()
    .build();

// Soft references for values (GC under memory pressure)
Cache<String, LargeObject> softValueCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .softValues()
    .build();

Constraints:

  • Weak/soft references use identity comparison (==) instead of equals()
  • Cannot use weak/soft values with async caches

Expiration Configuration

Configure time-based entry expiration using fixed or variable policies.

// Fixed expiration policies
public Caffeine<K, V> expireAfterWrite(Duration duration)
public Caffeine<K, V> expireAfterWrite(long duration, TimeUnit unit)
public Caffeine<K, V> expireAfterAccess(Duration duration)
public Caffeine<K, V> expireAfterAccess(long duration, TimeUnit unit)

// Variable expiration policy
public <K1, V1> Caffeine<K1, V1> expireAfter(Expiry<? super K1, ? super V1> expiry)

Usage Example

// Fixed expiration after write
Cache<String, String> writeExpireCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(Duration.ofMinutes(10))
    .build();

// Fixed expiration after access  
Cache<String, String> accessExpireCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .expireAfterAccess(30, TimeUnit.MINUTES)
    .build();

// Variable expiration based on entry characteristics
Cache<String, String> variableExpireCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .expireAfter(Expiry.creating((key, value) -> 
        key.startsWith("temp_") ? Duration.ofMinutes(5) : Duration.ofHours(1)))
    .build();

Constraints: Cannot mix expireAfter(Expiry) with other expiration methods.

Refresh Configuration

Configure automatic background refresh for loading caches.

public Caffeine<K, V> refreshAfterWrite(Duration duration)
public Caffeine<K, V> refreshAfterWrite(long duration, TimeUnit unit)

Usage Example

LoadingCache<String, String> refreshingCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .refreshAfterWrite(Duration.ofMinutes(5))
    .build(key -> fetchFromDatabase(key));

// Old value remains available during refresh
String value = refreshingCache.get("key"); // Returns cached value while refreshing

Constraints: Only applicable to LoadingCache and AsyncLoadingCache instances.

Execution and Scheduling Configuration

Configure threading and scheduling for cache operations.

public Caffeine<K, V> executor(Executor executor)
public Caffeine<K, V> scheduler(Scheduler scheduler)
public Caffeine<K, V> ticker(Ticker ticker)

Usage Example

// Custom executor for async operations
ExecutorService customExecutor = Executors.newFixedThreadPool(4);
Cache<String, String> customExecCache = Caffeine.newBuilder()
    .executor(customExecutor)
    .maximumSize(1000)
    .build();

// Custom scheduler for maintenance
ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);
Cache<String, String> customSchedCache = Caffeine.newBuilder()
    .scheduler(Scheduler.forScheduledExecutorService(scheduledExecutor))
    .expireAfterWrite(Duration.ofMinutes(10))
    .maximumSize(1000)
    .build();

// Custom ticker for testing
Cache<String, String> testCache = Caffeine.newBuilder()
    .ticker(Ticker.disabledTicker()) // Always returns 0
    .expireAfterWrite(Duration.ofMinutes(10))
    .maximumSize(1000)
    .build();

Listener Configuration

Configure callbacks for cache entry removal events.

public <K1, V1> Caffeine<K1, V1> evictionListener(RemovalListener<? super K1, ? super V1> evictionListener)
public <K1, V1> Caffeine<K1, V1> removalListener(RemovalListener<? super K1, ? super V1> removalListener)

Usage Example

// Eviction listener (called during cache operations)
Cache<String, String> evictionListenerCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .evictionListener((key, value, cause) -> {
        if (cause.wasEvicted()) {
            System.out.println("Evicted: " + key + " -> " + value + " (" + cause + ")");
        }
    })
    .build();

// Removal listener (called asynchronously)
Cache<String, String> removalListenerCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .removalListener((key, value, cause) -> {
        System.out.println("Removed: " + key + " -> " + value + " (" + cause + ")");
        // Cleanup resources, log to external system, etc.
    })
    .build();

Difference:

  • evictionListener: Called synchronously during cache operations
  • removalListener: Called asynchronously for all removal events

Statistics Configuration

Enable cache performance tracking and statistics collection.

public Caffeine<K, V> recordStats()
public Caffeine<K, V> recordStats(Supplier<? extends StatsCounter> statsCounterSupplier)

Usage Example

// Basic statistics recording
Cache<String, String> statsCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .recordStats()
    .build();

CacheStats stats = statsCache.stats();
System.out.println("Hit rate: " + stats.hitRate());

// Custom statistics counter
Cache<String, String> customStatsCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .recordStats(ConcurrentStatsCounter::new)
    .build();

Terminal Methods

Create the actual cache instances from the configured builder.

// Synchronous cache creation
public <K1 extends K, V1 extends V> Cache<K1, V1> build()
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(CacheLoader<? super K1, V1> loader)

// Asynchronous cache creation
public <K1 extends K, V1 extends V> AsyncCache<K1, V1> buildAsync()
public <K1 extends K, V1 extends V> AsyncLoadingCache<K1, V1> buildAsync(CacheLoader<? super K1, V1> loader)
public <K1 extends K, V1 extends V> AsyncLoadingCache<K1, V1> buildAsync(AsyncCacheLoader<? super K1, V1> loader)

Usage Example

// Manual cache
Cache<String, String> manualCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .build();

// Loading cache with CacheLoader
LoadingCache<String, String> loadingCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .build(key -> "loaded_" + key);

// Async cache
AsyncCache<String, String> asyncCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .buildAsync();

// Async loading cache with CacheLoader
AsyncLoadingCache<String, String> asyncLoadingCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .buildAsync(key -> "async_loaded_" + key);

// Async loading cache with AsyncCacheLoader
AsyncLoadingCache<String, String> asyncLoaderCache = Caffeine.newBuilder()
    .maximumSize(1000)
    .buildAsync((key, executor) -> CompletableFuture.supplyAsync(() -> "async_" + key, executor));

Configuration Validation

The builder performs runtime validation to prevent incompatible configuration combinations:

  • Size vs Weight: Cannot use both maximumSize() and maximumWeight()
  • Expiration Exclusivity: Cannot mix expireAfter(Expiry) with fixed expiration methods
  • Async Limitations: Cannot use weak/soft values with async caches
  • Refresh Requirements: refreshAfterWrite() only works with loading cache types

Attempting incompatible combinations will throw IllegalStateException during cache creation.

Install with Tessl CLI

npx tessl i tessl/maven-com-github-ben-manes-caffeine--caffeine

docs

asynchronous-caching.md

cache-construction.md

cache-policies.md

functional-interfaces.md

index.md

statistics.md

synchronous-caching.md

tile.json