How to Implement an LRU Cache in Java with Generics and O(1) Operations?

Question

How can I implement a Least Recently Used (LRU) cache in Java using Generics and achieve O(1) operations?

// Sample code for an LRU Cache in Java with Generics
import java.util.*;

public class LRUCache<K, V> {
    private final int capacity;
    private final Map<K, Node<K, V>> cache;
    private final DoublyLinkedList<K, V> list;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.cache = new HashMap<>();
        this.list = new DoublyLinkedList<>();
    }

    public V get(K key) {
        if (!cache.containsKey(key)) return null;
        Node<K, V> node = cache.get(key);
        list.moveToFront(node);
        return node.value;
    }

    public void put(K key, V value) {
        if (cache.containsKey(key)) {
            Node<K, V> node = cache.get(key);
            node.value = value;
            list.moveToFront(node);
        } else {
            if (cache.size() == capacity) {
                Node<K, V> last = list.removeLast();
                cache.remove(last.key);
            }
            Node<K, V> newNode = list.addFront(key, value);
            cache.put(key, newNode);
        }
    }
}

class Node<K, V> {
    K key;
    V value;
    Node<K, V> prev, next;
    Node(K key, V value) { this.key = key; this.value = value; }
}

class DoublyLinkedList<K, V> {
    private Node<K, V> head, tail;

    public DoublyLinkedList() {
        head = new Node<>(null, null);
        tail = new Node<>(null, null);
        head.next = tail;
        tail.prev = head;
    }

    public Node<K, V> addFront(K key, V value) {
        Node<K, V> newNode = new Node<>(key, value);
        newNode.next = head.next;
        newNode.prev = head;
        head.next.prev = newNode;
        head.next = newNode;
        return newNode;
    }

    public void moveToFront(Node<K, V> node) {
        remove(node);
        addFront(node.key, node.value);
    }

    public Node<K, V> removeLast() {
        Node<K, V> toRemove = tail.prev;
        remove(toRemove);
        return toRemove;
    }

    private void remove(Node<K, V> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
}

Answer

The Least Recently Used (LRU) cache is a classic data structure essential for optimizing space and performance in memory management. This implementation ensures that both retrieval and insertion operations occur in O(1) time complexity, making it highly efficient for real-world applications.

// See the provided code snippet for a complete implementation of LRU Cache.

Causes

  • LRU cache helps manage data efficiently by discarding the least used items when space is needed.
  • In applications where memory and speed are vital, managing cache with O(1) operations prevents bottlenecks.

Solutions

  • Utilize a HashMap to store cache entries indexed by key for O(1) retrieval.
  • Implement a Doubly Linked List to track the order of use, allowing easy addition to the front and removal from the end with O(1) complexity.
  • Combine both data structures to maintain a quick access list and a fast lookup.

Common Mistakes

Mistake: Not managing the capacity correctly, leading to memory leaks.

Solution: Always check the capacity before adding a new element and remove the least used correctly.

Mistake: Inefficient retrieval methods that lead to O(n) complexity.

Solution: Ensure the get() method updates the usage order effectively.

Helpers

  • LRU cache in Java
  • Java Generics
  • O(1) cache operations
  • Least Recently Used cache
  • Java data structures
  • efficient caching techniques

Related Questions

⦿How to Optimize a For Loop in Java for Performance?

Explore efficient for loop optimization techniques in Java focusing on performance improvements for large data structures like ArrayLists.

⦿How to Sort a List of Integers in Java?

Learn how to easily sort a ListInteger in Java with builtin methods. Explore examples explanations and common mistakes.

⦿Should You Use a `for` Loop or a `while` Loop for Iteration in Java?

Explore the differences between using a for loop and a while loop for iteration in Java. Discover best practices and tips for clean maintainable code.

⦿How to Implement a Simple File Download Servlet in Java

Learn how to create a simple file download servlet in Java that allows users to download files through GET requests.

⦿How to Create Guava Multimaps Concisely?

Learn to create Guava Multimaps more compactly with tips and examples for efficient implementation.

⦿Understanding the Role of Volatile in Double-Checked Locking for Singleton Instances

Explore the importance of volatile in doublechecked locking within Singleton patterns in Java to ensure thread safety and performance.

⦿How to Convert a List of Custom Class Objects to a List of Strings Using Java 8 Lambdas?

Learn how to use Java 8 lambdas to transform a list of custom objects into a list of strings with examples and explanations.

⦿How to Convert Snake Case to Camel Case in Java?

Learn how to convert a string from snake case to camel case in Java with clear explanations and code examples.

⦿Understanding Final Variables and Immutability in Java

Learn the distinction between final variables and immutability in Java and how they affect variable manipulation and object states.

© Copyright 2025 - CodingTechRoom.com