Library

LRU Cache

Keep a fixed number of entries and evict the least recently used item when the cache is full.

JAVASCRIPT Free to use
Code
class LruCache {
    constructor(capacity) {
        if (!Number.isInteger(capacity) || capacity < 1) {
            throw new RangeError('Capacity must be a positive integer.');
        }

        this.capacity = capacity;
        this.items = new Map();
    }

    get size() {
        return this.items.size;
    }

    has(key) {
        return this.peek(key) !== undefined;
    }

    get(key) {
        const entry = this.read(key);
        if (!entry) {
            return undefined;
        }

        this.items.delete(key);
        this.items.set(key, entry);
        return entry.value;
    }

    peek(key) {
        const entry = this.read(key);
        return entry ? entry.value : undefined;
    }

    set(key, value, ttlMs = null) {
        if (value === undefined) {
            throw new TypeError('undefined cannot be stored. Use delete() instead.');
        }

        if (this.items.has(key)) {
            this.items.delete(key);
        } else if (this.items.size >= this.capacity) {
            this.dropExpired();
            if (this.items.size >= this.capacity) {
                const oldest = this.items.keys().next().value;
                this.items.delete(oldest);
            }
        }

        this.items.set(key, {
            value,
            expiresAt: ttlMs == null ? null : Date.now() + ttlMs,
        });

        return this;
    }

    delete(key) {
        return this.items.delete(key);
    }

    clear() {
        this.items.clear();
    }

    read(key) {
        const entry = this.items.get(key);
        if (!entry) {
            return null;
        }

        if (entry.expiresAt != null && Date.now() > entry.expiresAt) {
            this.items.delete(key);
            return null;
        }

        return entry;
    }

    dropExpired() {
        for (const [key, entry] of this.items) {
            if (entry.expiresAt != null && Date.now() > entry.expiresAt) {
                this.items.delete(key);
            }
        }
    }
}
Quick try
const cache = new LruCache(3);

cache.set('a', 1).set('b', 2).set('c', 3);
cache.get('a');
cache.set('d', 4); // drops b

console.log(cache.get('b')); // undefined
console.log(cache.peek('c')); // 3, order unchanged
console.log([...cache.items.keys()]); // ['c', 'a', 'd']

cache.set('token', 'abc', 2000); // expires in 2s

What it does

  • A JavaScript Map keeps insertion order, so delete-then-set is enough. No doubly linked list is required.
  • get moves the entry to the end. peek reads it without changing the order.
  • An optional TTL is supported. An expired entry is removed on read, or when space is needed.

Where it fits

A practical place for this snippet in a real project.

Useful for a request result or a computed page in the UI. It is not a database, and it does not replace an explicit invalidate when data changes.

Similar snippets

Binary Search Tree
JAVASCRIPT

Binary Search Tree

Insert, search, and delete while keeping values sorted. Average O(log n), worst O(n) if the tree becomes a chain.

Function Memoization
JAVASCRIPT

Function Memoization

Wrap a function and reuse its result for the same inputs. The next call with the same values skips the work.

Breadth and Depth Traversal
JAVASCRIPT

Breadth and Depth Traversal

An undirected graph: visit in breadth or depth, find the shortest hop path, and detect a cycle without counting the walk back to a parent.

تحتاج مقتطفاً غير موجود؟

صف المشكلة أو الفكرة، وسأرى إن كان مناسباً إضافته للمكتبة.