Introduction: Why is caching needed in Java?
Modern Java applications often work with large amounts of data. Each request to a database or external API costs time and resources. Without caching, as load increases, performance drops and response time increases. Caching allows storing frequently requested data in fast access (in RAM), which reduces latency and decreases backend load.
In Java, there are three main approaches to caching: built-in solutions (for example, HashMap or Caffeine), distributed systems (Redis and Memcached). In this article, we will analyze each of them, provide code examples, and help you choose the optimal option for your project.
1. Built-in caching in Java
Built-in caching is the simplest way to speed up an application. Data is stored directly in the JVM memory. Main advantages: minimal access latency, ease of setup. Disadvantages: limited capacity (depends on heap), data is lost upon application restart.
1.1. Simple caching via HashMap
The most basic option is to use a ConcurrentHashMap with manual time-to-live management. Suitable for prototypes, but not for production (no automatic eviction, possible memory leaks).
import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;
public class SimpleCache { private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
public void put(String key, Object value, long ttlMillis) { cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMillis)); }
public Object get(String key) { CacheEntry entry = cache.get(key); if (entry == null || System.currentTimeMillis() > entry.expiry) { cache.remove(key); return null; } return entry.value; }
private static class CacheEntry { private final Object value; private final long expiry; // constructor and getters }}1.2. Caffeine — a modern caching library
Caffeine is a high-performance library for Java, used by default in Spring Cache. It supports automatic eviction by time, size, as well as weighted elements. Caffeine is faster than Guava Cache (on which it is based).
import com.github.benmanes.caffeine.cache.Cache;import com.github.benmanes.caffeine.cache.Caffeine;import java.util.concurrent.TimeUnit;
public class CaffeineExample { public static void main(String[] args) { Cache<String, String> cache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000) .build();
cache.put("user:123", "John Doe"); String user = cache.getIfPresent("user:123"); System.out.println("Cached user: " + user); }}For production, it is recommended to use Caffeine or Ehcache (which supports disk storage). Built-in solutions are ideal for microservices and single-instance monoliths.
2. Memcached: distributed caching for Java
Memcached is a distributed caching system that operates in RAM. It is simple, fast, and supports horizontal scaling. Main features:
- Storage in the form of key-value pairs (maximum value size — 1 MB).
- Does not support persistence (data is lost upon restart).
- No built-in authentication or encryption.
To work with Memcached in Java, the SpyMemcached library is most often used, or
Blogs
Book Recommendations
Read also