java 50 lines · 7 steps

A thread-safe LRU cache in Java

A LinkedHashMap in access order plus a read-write lock gives a bounded, concurrent least-recently-used cache.

Explained by highlit
1import java.util.LinkedHashMap;
2import java.util.Map;
3import java.util.concurrent.locks.ReentrantReadWriteLock;
4 
5public class LruCache<K, V> {
6 
7 private final int capacity;
8 private final Map<K, V> cache;
9 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
10 
11 public LruCache(int capacity) {
12 if (capacity <= 0) {
13 throw new IllegalArgumentException("capacity must be positive");
14 }
15 this.capacity = capacity;
16 this.cache = new LinkedHashMap<>(capacity, 0.75f, true) {
17 @Override
18 protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
19 return size() > LruCache.this.capacity;
20 }
21 };
22 }
23 
24 public V get(K key) {
25 lock.writeLock().lock();
26 try {
27 return cache.get(key);
28 } finally {
29 lock.writeLock().unlock();
30 }
31 }
32 
33 public void put(K key, V value) {
34 lock.writeLock().lock();
35 try {
36 cache.put(key, value);
37 } finally {
38 lock.writeLock().unlock();
39 }
40 }
41 
42 public int size() {
43 lock.readLock().lock();
44 try {
45 return cache.size();
46 } finally {
47 lock.readLock().unlock();
48 }
49 }
50}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1LinkedHashMap in access-order mode does the LRU bookkeeping for you — reordering entries on every access.
  2. 2Overriding removeEldestEntry turns a plain map into a self-evicting bounded cache.
  3. 3Reads that mutate access order must take a write lock, since they change the map's internal state.

Related explainers

Share this explainer

Here's the card — post it anywhere.

A thread-safe LRU cache in Java — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code