Redis Data Structures in Java: A Practical Guide with Redisson
People often think of Redis as a key-value store for strings, but that undersells it. Redis (and Valkey, its open-source fork) is really a data structure server: it stores hashes, lists, sets, sorted sets, counters, and more, each with its own commands and performance characteristics.
The challenge for Java developers is that those structures live on the server and are manipulated through a wire protocol, not through the collection types you already know. Redisson closes that gap. It exposes each Redis data structure as a distributed implementation of a familiar Java interface, so a Redis hash becomes a Map, a Redis list becomes a List, and so on, backed by the server and shared across every instance of your application.
This guide walks through the core structures with runnable code, then points you to the more specialized ones. Every example works identically against Redis and Valkey.
The snippets below assume you already have a
RedissonClientnamedredisson. If you don't, How to Use Redis in Java covers installing the dependency and connecting in a few minutes.
The Redis-to-Java Mapping
Here's the mental model. Each Redis data type has a Redisson object, and most map onto an interface from java.util:
| Redis / Valkey type | Redisson object | Familiar Java interface |
|---|---|---|
| String / object | RBucket | object holder |
| Hash | RMap, RMapCache | ConcurrentMap |
| List | RList | List |
| Set | RSet | Set |
| Sorted set | RScoredSortedSet, RSortedSet | score-ordered / SortedSet |
| Bitmap | RBitSet | BitSet |
| Counters | RAtomicLong, RAtomicDouble, RLongAdder | AtomicLong |
| Queues | RQueue, RDeque, RBlockingQueue | Queue, Deque, BlockingQueue |
Because these implement standard interfaces, most of your code reads exactly like ordinary Java, the difference is where the data lives. See the full Redis data types reference for the underlying commands.
Strings and Objects: RBucket
The simplest structure is a single value under a key. Redisson calls this an RBucket, and it can hold any serializable object, not just a string:
import org.redisson.api.RBucket;
RBucket<String> bucket = redisson.getBucket("user:1001:name");
bucket.set("Ada");
String name = bucket.get(); // Ada
Use a bucket for cached objects, feature flags, or any standalone value. You can also set a time-to-live so the value expires automatically.
Hashes: RMap
A Redis hash stores field-value pairs under one key, perfect for representing an object like a user or a product. RMap implements java.util.concurrent.ConcurrentMap, so it behaves like a Map you already know:
import org.redisson.api.RMap;
RMap<String, String> user = redisson.getMap("user:1001");
user.put("name", "Ada");
user.put("role", "engineer");
String role = user.get("role"); // engineer
boolean hasName = user.containsKey("name"); // true
Under the hood this is a single Redis hash; Redisson gives you the Java Map API on top. If you need per-entry TTL or eviction, reach for RMapCache.
Lists: RList
A Redis list is an ordered, index-addressable collection. RList implements java.util.List:
import org.redisson.api.RList;
RList<String> tasks = redisson.getList("build:tasks");
tasks.add("compile");
tasks.add("test");
tasks.add("deploy");
int count = tasks.size(); // 3
String first = tasks.get(0); // compile
Lists preserve insertion order and allow duplicates, which makes them a natural fit for timelines, activity logs, and simple job lists.
Sets: RSet
A set holds unique, unordered elements. RSet implements java.util.Set, so duplicates are silently ignored:
import org.redisson.api.RSet;
RSet<String> tags = redisson.getSet("post:42:tags");
tags.add("redis");
tags.add("java");
tags.add("redis"); // ignored, already present
boolean tagged = tags.contains("java"); // true
Sets are ideal for membership checks, deduplication, and tag or permission tracking. Redis also supports set operations like unions and intersections directly on the server.
Sorted Sets: RScoredSortedSet
A sorted set assigns each element a numeric score and keeps the elements ordered by it, the structure behind most leaderboards and priority rankings. RScoredSortedSet exposes score-based ordering:
import org.redisson.api.RScoredSortedSet;
import java.util.Collection;
RScoredSortedSet<String> board = redisson.getScoredSortedSet("game:leaderboard");
board.add(100, "alice");
board.add(85, "bob");
board.add(120, "carol");
Integer carolRank = board.revRank("carol"); // 0 — highest score ranks first
Collection<String> topThree = board.valueRangeReversed(0, 2); // [carol, alice, bob]
For a full worked example, see How to Build a Real-Time Leaderboard in Java with Valkey or Redis. If you want comparator-based ordering instead of scores, RSortedSet implements java.util.SortedSet.
Counters: RAtomicLong and RAtomicDouble
When many machines need to increment a shared value, a normal variable won't do, you need atomic operations that happen on the server. RAtomicLong is a distributed version of java.util.concurrent.atomic.AtomicLong:
import org.redisson.api.RAtomicLong;
RAtomicLong views = redisson.getAtomicLong("page:home:views");
views.incrementAndGet(); // 1
views.addAndGet(10); // 11
long total = views.get(); // 11
RAtomicDouble does the same for floating-point values, and RLongAdder is a higher-throughput option when you have many concurrent writers and only occasionally read the total. These are the building blocks for view counters, rate meters, and ID generators.
Beyond the Core Data Structures
Redisson maps well over 50 objects and services onto Redis and Valkey. Once the core collections feel natural, these specialized structures are worth knowing:
- Probabilistic structures. A Bloom filter or Cuckoo filter answers "have I seen this before?" using a fraction of the memory a set would need, at the cost of a small false-positive rate. HyperLogLog estimates cardinality of huge sets cheaply.
- JSON. Store and query structured documents with a JSON holder instead of flattening objects into hashes, see storing JSON with Redis on Java.
- Time series. Append timestamped values for metrics and events with a Redis-based time series collection.
- Geospatial. Index coordinates and run radius queries for location-based search.
- Vector sets. Store embeddings for similarity search directly in Valkey or Redis, see the vector sets guide.
Locks and Synchronizers
Redisson also builds coordination primitives on top of Redis. An RLock implements java.util.concurrent.locks.Lock but works across processes and machines, so only one node runs a critical section at a time. Because locks come with their own subtleties, lease times, fair ordering, and failover, they're covered in depth in How to Use Redis Locks in Java. The same family includes distributed semaphores, read-write locks, and count-down latches.
Choosing the Right Structure
A quick rule of thumb:
- Storing one value or a cached object → RBucket.
- Representing an entity with fields → RMap (hash).
- Ordered items with duplicates, like a log → RList.
- Unique membership or deduplication → RSet.
- Ranking by a score, like a leaderboard → RScoredSortedSet.
- A shared counter updated concurrently → RAtomicLong.
Picking the structure that matches your access pattern matters more for performance than any client-side tuning, because it determines which server-side commands run.
Sync, Async, Reactive, and RxJava
Every object shown here has four API flavors: synchronous (used above), asynchronous (RMapAsync, etc.), Reactive Streams, and RxJava3. You can mix them, use the blocking API for simple paths and the reactive one where you need backpressure, without changing how the data is stored.
Frequently Asked Questions
What Data Structures Does Redis Support?
Strings, hashes, lists, sets, sorted sets, bitmaps, and specialized types like HyperLogLog, streams, and geospatial and JSON structures. Redisson exposes each as a distributed Java object.
How Do I Use a Redis Hash in Java?
Call redisson.getMap("key") to get an RMap, which implements ConcurrentMap. Use put, get, and containsKey exactly as you would with a normal map; the data is stored as a Redis hash on the server.
What Is the Java Equivalent of a Redis Sorted Set?
Redisson's RScoredSortedSet, which orders elements by a numeric score, ideal for leaderboards and rankings. For comparator-based ordering, RSortedSet implements java.util.SortedSet.
Do These Data Structures Work With Valkey?
Yes. Valkey is wire-compatible with Redis, so every object and example here works against Valkey without changes.
Next Steps
You now have the core Redis and Valkey data structures mapped to Java, with the code to use each one. If you're just getting set up, start with How to Use Redis in Java; to go deeper on any object, the full Redisson documentation covers all 50-plus structures and services.
For workloads that need local caching, data partitioning, or advanced eviction on top of these same objects, Redisson PRO adds them without changing your code. You can try it for free.