eviction-recency
Least-recently-used cache eviction
LeastRecentlyUsed is an EvictionStrategy that, while its capacity is exceeded, removes the key whose last read or insert is oldest.
Rationale
Why. Keys used a moment ago tend to be used again soon.
Key Concepts
Recency
Role. Each Insert and Hit makes its key the most recent. A Miss changes nothing.
Pattern. STRATEGY, OBSERVER
How It Works
Guarantees. No public parameter takes null and no public method returns it, declared with contrax's @PreCondition(IsNotNull.class) and @PostCondition(IsNotNull.class).
Thread safety. An instance is not thread-safe: events must reach update one at a time.
Lane
Purpose. Eviction for workloads where recent use predicts the next.
Alternative. eviction-frequency when long-run popularity predicts better; eviction-insertion-order when reads must not change the order.
When to avoid. A scan over more keys than the capacity holds: each one pushes out a key that may be asked for next.
Usage
Room for two: reading a again keeps it, so b leaves
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
import software.visionary.cache.Cache;
import software.visionary.cache.capacity.fixed.FixedSize;
import software.visionary.cache.events.CacheEvent;
import software.visionary.cache.events.Evict;
import software.visionary.cache.eviction.recency.LeastRecentlyUsed;
import software.visionary.cache.policy.CachePolicy;
import software.visionary.cache.topology.read.through.ReadThroughCacheFactory;
import software.visionary.events.Observer;
Map<String, Integer> source = Map.of("a", 1, "b", 2, "c", 3);
Supplier<Cache<String, Integer>> caches = new ReadThroughCacheFactory<>(
key -> Optional.ofNullable(source.get(key)),
new CachePolicy<>(() -> new FixedSize<>(2), LeastRecentlyUsed::new, Instant::now));
Observer<CacheEvent<String, ?>> printEvictions = event -> {
if (event instanceof Evict<String, ?> evicted) { System.out.println("evicted " + evicted.key()); }
};
var cache = caches.get();
cache.add(printEvictions);
Stream.of("a", "b", "a", "c").forEach(cache::apply);
Output
evicted bDependencies
software.visionary:cache:2026.10.13at Compilesoftware.visionary.contrax:processor:2026.10.13at Processorsoftware.visionary:junit-closure:2026.09.17at Testing
Views
Drawn from the release. A link in a view opens its source at the release tag.