A flexible and extensible in-memory cache implementation in Java with support for multiple eviction policies.
This library provides a generic cache implementation with pluggable eviction policies. It allows developers to store key-value pairs in memory with automatic eviction of entries when the cache reaches its capacity limit.
- Generic type support for both keys and values
- Multiple eviction policies:
- LRU (Least Recently Used)
- LFU (Least Frequently Used)
- FIFO (First In First Out)
- LIFO (Last In First Out)
- Random
- Configurable capacity
- Extensible design for custom eviction policies
// Create an LRU cache with capacity of 100
Cache<String, User> userCache = CacheFactory.getCache(EvictionPolicy.LRU, 100);
// Create an LFU cache with capacity of 50
Cache<Integer, String> dataCache = CacheFactory.getCache(EvictionPolicy.LFU, 50);
// Store a value
userCache.put("user123", new User("John Doe"));
// Retrieve a value
Optional<User> user = userCache.get("user123");
// Check cache size
int cacheSize = userCache.size();
The library supports the following eviction policies:
Evicts the least recently accessed entries first. Best for access patterns with temporal locality.
Evicts entries that are used least frequently. Good for access patterns where popularity matters more than recency.
Evicts the oldest entries first, operating like a queue. Simple and predictable.
Evicts the newest entries first, operating like a stack.
Evicts entries at random. Simple but can be useful in certain scenarios.
The project follows a clean, modular architecture:
Cache
: Main interface for cache operationsCacheFactory
: Factory to create appropriate cache instancesCacheImpl
: Core implementation of the Cache interfaceEvictionPolicy
: Interface for pluggable eviction strategiesStorage
: Interface for underlying data storage
Cache (Interface)
↑
CacheImpl ──────► Storage ◄─── HashMapStorage
│ ↑
│ └─── ArrayListStorage
│
└───► EvictionPolicy ◄─── OrderBasedEvictionPolicy ◄─── LRUEvictionPolicy
↑ ↑ └─── FIFOEvictionPolicy
│ └─── LIFOEvictionPolicy
│ └─── DefaultEvictionPolicy
└─── LFUEvictionPolicy
The library uses the following data structures:
HashMap
: For O(1) key-value lookupsDoublyLinkedList
: For efficient implementation of ordering-based policies- Custom data structures for frequency tracking in LFU
The cache operations have the following time complexities:
get
: O(1) for all policiesput
: O(1) for all policies- Eviction: O(1) for all policies
// Create an LRU cache with capacity of 3
Cache<String, String> lruCache = CacheFactory.getCache(EvictionPolicy.LRU, 3);
// Add entries
lruCache.put("key1", "value1");
lruCache.put("key2", "value2");
lruCache.put("key3", "value3");
// Access key1 (making key2 the least recently used)
lruCache.get("key1");
// Add a new entry, which will evict key2
lruCache.put("key4", "value4");
// key2 should be evicted
assert lruCache.get("key2").isEmpty();
// Create an LFU cache with capacity of 3
Cache<Integer, Integer> lfuCache = CacheFactory.getCache(EvictionPolicy.LFU, 3);
// Add entries
lfuCache.put(1, 10);
lfuCache.put(2, 20);
lfuCache.put(3, 30);
// Access key1 multiple times
lfuCache.get(1);
lfuCache.get(1);
// Access key2 once
lfuCache.get(2);
// Add a new entry, which will evict key3 (least frequently used)
lfuCache.put(4, 40);
// key3 should be evicted
assert lfuCache.get(3).isEmpty();
This library is designed to be extensible. Here are some ways to extend it:
Implement the EvictionPolicy
interface to create your own eviction strategy:
public class MyCustomEvictionPolicy<K> implements EvictionPolicy<K> {
// Implement the required methods
}
You can also implement your own storage mechanism:
public class MyCustomStorage<K, V> implements Storage<K, V> {
// Implement the required methods
}
The library includes comprehensive unit tests for each eviction policy and core components:
DefaultCacheTest
: Basic cache functionality testsLRUCacheTest
: Tests specific to LRU evictionLFUCacheTest
: Tests specific to LFU evictionFIFOCacheTest
: Tests specific to FIFO evictionLIFOCacheTest
: Tests specific to LIFO evictionDoublyLinkedListTest
: Tests for the internal data structure
- Java 17 or higher
- JUnit 5 for tests
This project is licensed under the MIT License - see the LICENSE file for details.