Introduction: Why is caching needed in Java?
\nIn modern high-load development, data access speed is a critical factor. Every request to a database or external API increases response time and infrastructure load. Caching in Java allows storing frequently requested data in fast memory (RAM), reducing response time from tens of milliseconds to microseconds.
\nIn this article, we will cover three main approaches to caching: built-in solutions (HashMap, Caffeine, Ehcache), Redis, and Memcached. You will learn how to choose the right tool and see working code examples.
\n\n1. Built-in Solutions for Caching in Java
\nFor small projects or single-threaded applications, built-in collections are often sufficient. However, for production environments, it is better to use specialized libraries.
\n\n1.1. Simple Cache using HashMap
\nThe simplest way is to use a ConcurrentHashMap with manual time-to-live management. Suitable for prototypes, but lacks eviction mechanisms.
import java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\npublic class SimpleCache {\n private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();\n\n public void put(String key, Object value, long ttlMs) {\n cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMs));\n }\n\n public Object get(String key) {\n CacheEntry entry = cache.get(key);\n if (entry == null || System.currentTimeMillis() > entry.expiry) {\n cache.remove(key);\n return null;\n }\n return entry.value;\n }\n\n private record CacheEntry(Object value, long expiry) {}\n}\n\n1.2. Caffeine — High-Performance Cache for Java
\nCaffeine is a modern library used in Spring Cache. It supports automatic eviction by time, size, and access frequency.
\nimport com.github.benmanes.caffeine.cache.Cache;\nimport com.github.benmanes.caffeine.cache.Caffeine;\nimport java.util.concurrent.TimeUnit;\n\npublic class CaffeineExample {\n public static void main(String[] args) {\n Cache<String, String> cache = Caffeine.newBuilder()\n .expireAfterWrite(10, TimeUnit.MINUTES)\n .maximumSize(1000)\n .build();\n\n cache.put("user_1", "Alexey");\n String user = cache.getIfPresent("user_1");\n System.out.println(user); // Alexey\n }\n}\n\n1.3. Ehcache — Enterprise Standard
\nEhcache is a mature solution with support for clustering and disk persistence. It is often used in conjunction with Hibernate.
\nimport org.ehcache.Cache;\nimport org.ehcache.CacheManager;\nimport org.ehcache.config.builders.CacheConfigurationBuilder;\nimport org.ehcache.config.builders.CacheManagerBuilder;\nimport org.ehcache.config.builders.ResourcePoolsBuilder;\n\npublic class EhcacheExample {\n public static void main(String[] args) {\n CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()\n .withCache("users",\n CacheConfigurationBuilder.newCacheConfigurationBuilder(\n String.class, String.class,\n ResourcePoolsBuilder.heap(100))\n ).build();\n cacheManager.init();\n\n Cache<String, String> cache = cacheManager.getCache("users", String.class, String.class);\n cache.put("user_2", "Maria");\n System.out.println(cache.get("user_2")); // Maria\n\n cacheManager.close();\n }\n}\n\n2. Redis — Distributed Caching for Java
\nRedis is an in-memory data store that runs as a separate s