Problem
In test scenarios or lightweight application components, there is a need for a simple, thread-safe, in-memory data store that can temporarily hold a limited number of objects. The store should be easy to use, avoid external dependencies (e.g., databases), support generation and use of unique identifiers as keys, and automatically evict the oldest entries when a predefined capacity is exceeded. This enables predictable memory usage while providing fast access to recently stored data.
Solution
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MemoryStore<T> {
private final Lock lock = new ReentrantLock();
private final int maxElements;
private final Map<String, T> data = new LinkedHashMap<>() {
// called during put and ensures the map doesn't grow
@Override
protected boolean removeEldestEntry(Map.Entry<String, T> eldest) {
return size() > maxElements;
}
};
public MemoryStore(int maxElements) {
if (maxElements < 1) {
throw new IllegalArgumentException("maxElements must be > 1");
}
this.maxElements = maxElements;
}
public void store(T value) {
this.store(UUID.randomUUID().toString(), value);
}
public void store(String key, T value) {
lock.lock();
try {
data.put(key, value);
} finally {
lock.unlock();
}
}
public T get(String key) {
lock.lock();
try {
return data.get(key);
} finally {
lock.unlock();
}
}
public int size() {
lock.lock();
try {
return data.size();
} finally {
lock.unlock();
}
}
public LinkedHashMap<String, T> data() {
lock.lock();
try {
return new LinkedHashMap<>(this.data);
} finally {
lock.unlock();
}
}
}