Friday, June 27, 2025

Implement an LRU (Least Recently Used) cache in Java that removes the oldest object

 To implement an LRU (Least Recently Used) cache in Java that removes the oldest object when it's full, you can use an ordered data structure like `LinkedHashMap` or implement a custom data structure. 


Here's an example using `LinkedHashMap`, which makes implementing an LRU cache straightforward because it provides a constructor that allows you to specify "access-order." When the cache is full, we can evict the least recently used (oldest) entry.


### Implementation Using `LinkedHashMap`

Here is a simple implementation of an LRU Cache:


```java

import java.util.LinkedHashMap;

import java.util.Map;


public class LRUCache<K, V> {

    private final int capacity;

    private final Map<K, V> cache;


    public LRUCache(int capacity) {

        this.capacity = capacity;

        this.cache = new LinkedHashMap<K, V>(capacity, 0.75f, true) {

            @Override

            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {

                return size() > LRUCache.this.capacity;

            }

        };

    }


    public V get(K key) {

        return cache.getOrDefault(key, null);

    }


    public void put(K key, V value) {

        cache.put(key, value);

    }


    @Override

    public String toString() {

        return cache.toString();

    }


    public static void main(String[] args) {

        LRUCache<Integer, String> lruCache = new LRUCache<>(3);

        lruCache.put(1, "One");

        lruCache.put(2, "Two");

        lruCache.put(3, "Three");

        System.out.println("Cache: " + lruCache);

        

        // Access one of the existing keys

        lruCache.get(1);

        System.out.println("Cache After Accessing Key 1: " + lruCache);

        

        // Add another entry to trigger removal of the least recently used entry

        lruCache.put(4, "Four");

        System.out.println("Cache After Adding Key 4: " + lruCache);

    }

}

```


### Explanation

1. **Constructor for `LinkedHashMap`**:

   - The `LinkedHashMap` is initialized with the following parameters:

     - `capacity`: The initial capacity of the map.

     - `0.75f`: The load factor, which determines when the map resizes.

     - `true`: Enables access-order mode that orders the map entries based on access. The least recently accessed entry will be towards the beginning of the map.


2. **`removeEldestEntry` Method**:

   - This method is overridden to specify when the eldest entry (least recently used) should be removed. Here, we remove the eldest entry when the map's size exceeds the specified capacity.


3. **`put` and `get` Methods**:

   - The `put` method is used to insert key-value pairs.

   - The `get` method is used to retrieve the value associated with a key and update its access order.


4. **Behavior**:

   - When the cache reaches its capacity and a new key-value pair is added, the least recently used key-value pair is automatically removed from the cache.


### Output

When you run the `main` method, here's how the cache evolves:

```

Cache: {1=One, 2=Two, 3=Three}

Cache After Accessing Key 1: {2=Two, 3=Three, 1=One}

Cache After Adding Key 4: {3=Three, 1=One, 4=Four}

```


### Custom Implementation (Optional)

If you want more control or can't use `LinkedHashMap`, you can create your own LRU Cache using a combination of a `HashMap` for fast lookups and a doubly-linked list for maintaining the order of access. Let me know if you'd like to see this implementation!

No comments: