Java LinkedHashMap.removeEldestEntry method example

LinkedHashMap maintains a doubly-linked list across its entries, preserving insertion order (or access order, depending on configuration). Its protected removeEldestEntry() method lets you control automatic eviction — making it the simplest way to build a bounded cache in Java without any third-party library.


What Is removeEldestEntry()?

removeEldestEntry(Map.Entry<K,V> eldest) is a protected method called automatically after every put() or putAll(). If it returns true, LinkedHashMap removes the eldest (first) entry from the map. If it returns false, nothing is removed.

The default implementation always returns false — no automatic removal. You override it to add eviction logic.


Basic Example: Size-Bounded Map

Keep at most 4 entries — automatically evict the oldest when a 5th is added:

import java.util.*;

LinkedHashMap<Integer, String> boundedMap = new LinkedHashMap<>() {
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
        return size() > 4;
    }
};

boundedMap.put(0, "zero");
boundedMap.put(1, "one");
boundedMap.put(2, "two");
boundedMap.put(3, "three");

System.out.println("After 4 puts: " + boundedMap);
// {0=zero, 1=one, 2=two, 3=three}

boundedMap.put(4, "four"); // triggers eviction of key=0

System.out.println("After 5th put: " + boundedMap);
// {1=one, 2=two, 3=three, 4=four}

When the 5th entry is added, size() becomes 5, removeEldestEntry() returns true, and the entry with key 0 (the eldest) is automatically removed.


LRU Cache Using Access Order

For a true Least Recently Used (LRU) cache, construct LinkedHashMap with accessOrder = true. This moves accessed entries to the tail of the list, so the head always holds the least-recently-used entry:

int capacity = 3;

LinkedHashMap<String, String> lruCache = new LinkedHashMap<>(capacity, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        return size() > capacity;
    }
};

lruCache.put("a", "Apple");
lruCache.put("b", "Banana");
lruCache.put("c", "Cherry");
System.out.println(lruCache); // {a=Apple, b=Banana, c=Cherry}

lruCache.get("a"); // "a" accessed — moves to tail (most recent)
System.out.println(lruCache); // {b=Banana, c=Cherry, a=Apple}

lruCache.put("d", "Date"); // evicts "b" — least recently used
System.out.println(lruCache); // {c=Cherry, a=Apple, d=Date}

The LinkedHashMap(initialCapacity, loadFactor, accessOrder) constructor's third argument enables access-order mode. With accessOrder = true, every get() reorders the entry to the tail, so the head is always the LRU candidate for eviction.


Insertion Order vs Access Order

ModeHow It WorksWhat Gets Evicted
Insertion order (default)Entries stay in the order they were put()The entry that was inserted first
Access order (true)Accessed entries move to the tailThe entry least recently accessed or inserted

Reusable LRU Cache Class

import java.util.LinkedHashMap;
import java.util.Map;

public class LruCache<K, V> extends LinkedHashMap<K, V> {

    private final int maxSize;

    public LruCache(int maxSize) {
        super(maxSize, 0.75f, true); // accessOrder = true
        this.maxSize = maxSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > maxSize;
    }
}

// Usage:
LruCache<Integer, String> cache = new LruCache<>(5);
cache.put(1, "Page 1");
cache.put(2, "Page 2");
cache.get(1); // "1" is now most recently used
System.out.println(cache.containsKey(1)); // true

Thread Safety

LinkedHashMap is not thread-safe. For a concurrent LRU cache, wrap it with Collections.synchronizedMap():

Map<String, String> syncCache = Collections.synchronizedMap(
    new LruCache<>(100)
);

For high-concurrency workloads, consider ConcurrentHashMap with a manual size-bounding strategy, or a library like Caffeine which provides a lock-free LRU cache.


Summary

Override removeEldestEntry() in a LinkedHashMap subclass to automatically evict entries when the map exceeds a size limit. For a true LRU cache, construct LinkedHashMap with accessOrder = true so accesses move entries to the tail and the head always holds the least-recently-used entry. This pattern is clean, built into the JDK, and requires no external dependencies.

No comments :

Post a Comment

Please leave your message queries or suggetions.

Note: Only a member of this blog may post a comment.