Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java LinkedHashMap LRU cache: access order changes eviction

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

An access-ordered LinkedHashMap tracks recently accessed entries so a bounded cache can remove the least recently used entry after insertion.

Download Java source kit

This complete program targets Java 8. Its displayed output is checked by the tutorial validation script.

A read changes the eviction order

A document cache has space for two keys. It inserts invoice and receipt, reads invoice, then inserts statement. Receipt is evicted because the read promoted invoice to the most recent position. The printed key order makes that policy visible.

The capacity check belongs to removeEldestEntry and runs after insertion. The constructor rejects non-positive capacity rather than letting a zero-sized cache conceal a configuration error. This is a count bound, not a byte-size bound: one enormous document can still consume too much memory.

Define what the cache does not own

This fixture stores immutable strings in one thread. It has no expiry clock, fetch coalescing or persistence. A synchronized wrapper can serialize individual calls, but a lookup-then-load-then-put workflow needs its own coordination if duplicate remote work matters.

An access-ordered get changes iteration order. Do not assume that a read is harmless while another thread walks the keys. For a framework cache, Key identity and invalidation rules still determine whether a returned document belongs to the intended tenant.

Working program

Java
import java.util.*;
public class DocumentLruCache extends LinkedHashMap<String,String> {
    private final int capacity;
    DocumentLruCache(int capacity) {
        super(16,0.75f,true);
        if(capacity<1)throw new IllegalArgumentException("capacity");
        this.capacity=capacity;
    }
    protected boolean removeEldestEntry(Map.Entry<String,String> eldest){return size()>capacity;}
    public static void main(String[] args) {
        DocumentLruCache cache=new DocumentLruCache(2);
        cache.put("invoice","I");cache.put("receipt","R");cache.get("invoice");cache.put("statement","S");
        System.out.println(cache.keySet());System.out.println(cache.containsKey("receipt"));
        try{new DocumentLruCache(0);}catch(IllegalArgumentException rejected){System.out.println("capacity rejected");}
    }
}

Output

Output
[invoice, statement]
false
capacity rejected

Costs and boundaries

Expected hash lookup and access-order maintenance are constant work under ordinary key behavior. The cache retains at most capacity entries after insertion returns, plus a temporary new entry during the operation. Key/value sizes and hash quality remain part of the memory and latency budget.

Common Mistakes

  • Access ordering requires the access-order constructor setting.
  • A count limit is not a byte limit.
  • Do not assume cache get leaves iteration order unchanged.

Read next

Java LinkedHashMap: encounter order and a bounded cache model, Java collection views: live wrappers, snapshots and shallow copies, Spring cache keys: separate tenants and test the loader count.

java
lru-cache
Storage details