Skip to content

Commit 4c4c96e

Browse files
Support HRANDFIELD command via RedisMap.
Add randomKey() and randomEntry() to RedisHash. Update documentation and align methods with java terminology around keys vs. fields in hashes. Move Converters off their custom Map.Entry implementation and use SimpleImmutableEntry instead. Switch code that creates Map.Entry to the newly introduced Converters.entryOf method. See: #2048 Original Pull Request: #2104
1 parent a523b82 commit 4c4c96e

15 files changed

+185
-144
lines changed

src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java

+1-17
Original file line numberDiff line numberDiff line change
@@ -108,23 +108,7 @@ public StringRecord convert(ByteRecord source) {
108108
private boolean deserializePipelineAndTxResults = false;
109109

110110
private Entry<String, String> convertEntry(Entry<byte[], byte[]> source) {
111-
return new Entry<String, String>() {
112-
113-
@Override
114-
public String getKey() {
115-
return bytesToString.convert(source.getKey());
116-
}
117-
118-
@Override
119-
public String getValue() {
120-
return bytesToString.convert(source.getValue());
121-
}
122-
123-
@Override
124-
public String setValue(String value) {
125-
throw new UnsupportedOperationException("Cannot set value for entry");
126-
}
127-
};
111+
return Converters.entryOf(bytesToString.convert(source.getKey()), bytesToString.convert(source.getValue()));
128112
}
129113

130114
private class DeserializingConverter implements Converter<byte[], String> {

src/main/java/org/springframework/data/redis/connection/convert/Converters.java

+2-37
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,7 @@
1818
import java.io.StringReader;
1919
import java.nio.ByteBuffer;
2020
import java.time.Duration;
21-
import java.util.ArrayList;
22-
import java.util.Arrays;
23-
import java.util.Collection;
24-
import java.util.Collections;
25-
import java.util.LinkedHashMap;
26-
import java.util.LinkedHashSet;
27-
import java.util.List;
28-
import java.util.Map;
29-
import java.util.Properties;
30-
import java.util.Set;
21+
import java.util.*;
3122
import java.util.concurrent.TimeUnit;
3223

3324
import org.apache.commons.logging.Log;
@@ -472,7 +463,7 @@ public static Object parse(Object source, String sourcePath, Map<String, Class<?
472463
* @since 2.6
473464
*/
474465
public static <K, V> Map.Entry<K, V> entryOf(K key, V value) {
475-
return new SimpleEntry<>(key, value);
466+
return new AbstractMap.SimpleImmutableEntry<>(key, value);
476467
}
477468

478469
/**
@@ -653,30 +644,4 @@ private SlotRange parseSlotRange(String[] args) {
653644
}
654645

655646
}
656-
657-
private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
658-
659-
private final K key;
660-
private final V value;
661-
662-
public SimpleEntry(K key, V value) {
663-
this.key = key;
664-
this.value = value;
665-
}
666-
667-
@Override
668-
public K getKey() {
669-
return key;
670-
}
671-
672-
@Override
673-
public V getValue() {
674-
return value;
675-
}
676-
677-
@Override
678-
public V setValue(V value) {
679-
throw new UnsupportedOperationException();
680-
}
681-
}
682647
}

src/main/java/org/springframework/data/redis/core/BoundHashOperations.java

+15-15
Original file line numberDiff line numberDiff line change
@@ -89,49 +89,49 @@ public interface BoundHashOperations<H, HK, HV> extends BoundKeyOperations<H> {
8989
Double increment(HK key, double delta);
9090

9191
/**
92-
* Return a random field from the hash value stored at the bound key.
92+
* Return a random key (aka field) from the hash value stored at the bound key.
9393
*
94-
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
94+
* @return {@literal null} if the hash does not exist or when used in pipeline / transaction.
9595
* @since 2.6
9696
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
9797
*/
9898
@Nullable
99-
HK randomField();
99+
HK randomKey();
100100

101101
/**
102-
* Return a random field from the hash value stored at the bound key.
102+
* Return a random entry from the hash value stored at the bound key.
103103
*
104104
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
105105
* @since 2.6
106106
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
107107
*/
108108
@Nullable
109-
Map.Entry<HK, HV> randomValue();
109+
Map.Entry<HK, HV> randomEntry();
110110

111111
/**
112-
* Return a random field from the hash value stored at the bound key. If the provided {@code count} argument is
113-
* positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is
114-
* negative, the behavior changes and the command is allowed to return the same field multiple times. In this case,
115-
* the number of returned fields is the absolute value of the specified count.
112+
* Return a random keys (aka fields) from the hash value stored at the bound key. If the provided {@code count} argument is
113+
* positive, return a list of distinct keys, capped either at {@code count} or the hash size. If {@code count} is
114+
* negative, the behavior changes and the command is allowed to return the same key multiple times. In this case,
115+
* the number of returned keys is the absolute value of the specified count.
116116
*
117-
* @param count number of fields to return.
117+
* @param count number of keys to return.
118118
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
119119
* @since 2.6
120120
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
121121
*/
122122
@Nullable
123-
List<HK> randomFields(long count);
123+
List<HK> randomKeys(long count);
124124

125125
/**
126-
* Return a random field from the hash value stored at the bound key.
126+
* Return a random entry from the hash value stored at the bound key.
127127
*
128-
* @param count number of fields to return. Must be positive.
129-
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
128+
* @param count number of entries to return. Must be positive.
129+
* @return {@literal null} if the hash does not exist or when used in pipeline / transaction.
130130
* @since 2.6
131131
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
132132
*/
133133
@Nullable
134-
Map<HK, HV> randomValues(long count);
134+
Map<HK, HV> randomEntries(long count);
135135

136136
/**
137137
* Get key set (fields) of hash at the bound key.

src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ public Double increment(HK key, double delta) {
116116
*/
117117
@Nullable
118118
@Override
119-
public HK randomField() {
120-
return ops.randomField(getKey());
119+
public HK randomKey() {
120+
return ops.randomKey(getKey());
121121
}
122122

123123
/*
@@ -126,8 +126,8 @@ public HK randomField() {
126126
*/
127127
@Nullable
128128
@Override
129-
public Entry<HK, HV> randomValue() {
130-
return ops.randomValue(getKey());
129+
public Entry<HK, HV> randomEntry() {
130+
return ops.randomEntry(getKey());
131131
}
132132

133133
/*
@@ -136,8 +136,8 @@ public Entry<HK, HV> randomValue() {
136136
*/
137137
@Nullable
138138
@Override
139-
public List<HK> randomFields(long count) {
140-
return ops.randomFields(getKey(), count);
139+
public List<HK> randomKeys(long count) {
140+
return ops.randomKeys(getKey(), count);
141141
}
142142

143143
/*
@@ -146,8 +146,8 @@ public List<HK> randomFields(long count) {
146146
*/
147147
@Nullable
148148
@Override
149-
public Map<HK, HV> randomValues(long count) {
150-
return ops.randomValues(getKey(), count);
149+
public Map<HK, HV> randomEntries(long count) {
150+
return ops.randomEntries(getKey(), count);
151151
}
152152

153153
/*

src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java

+5-22
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public Double increment(K key, HK hashKey, double delta) {
9999
*/
100100
@Nullable
101101
@Override
102-
public HK randomField(K key) {
102+
public HK randomKey(K key) {
103103

104104
byte[] rawKey = rawKey(key);
105105
return deserializeHashKey(execute(connection -> connection.hRandField(rawKey), true));
@@ -111,7 +111,7 @@ public HK randomField(K key) {
111111
*/
112112
@Nullable
113113
@Override
114-
public Entry<HK, HV> randomValue(K key) {
114+
public Entry<HK, HV> randomEntry(K key) {
115115

116116
byte[] rawKey = rawKey(key);
117117
Entry<byte[], byte[]> rawEntry = execute(connection -> connection.hRandFieldWithValues(rawKey), true);
@@ -125,7 +125,7 @@ public Entry<HK, HV> randomValue(K key) {
125125
*/
126126
@Nullable
127127
@Override
128-
public List<HK> randomFields(K key, long count) {
128+
public List<HK> randomKeys(K key, long count) {
129129

130130
byte[] rawKey = rawKey(key);
131131
List<byte[]> rawValues = execute(connection -> connection.hRandField(rawKey, count), true);
@@ -138,7 +138,7 @@ public List<HK> randomFields(K key, long count) {
138138
*/
139139
@Nullable
140140
@Override
141-
public Map<HK, HV> randomValues(K key, long count) {
141+
public Map<HK, HV> randomEntries(K key, long count) {
142142

143143
Assert.isTrue(count > 0, "Count must not be negative");
144144
byte[] rawKey = rawKey(key);
@@ -324,24 +324,7 @@ public Cursor<Entry<HK, HV>> scan(K key, ScanOptions options) {
324324

325325
@Override
326326
public Entry<HK, HV> convert(final Entry<byte[], byte[]> source) {
327-
328-
return new Entry<HK, HV>() {
329-
330-
@Override
331-
public HK getKey() {
332-
return deserializeHashKey(source.getKey());
333-
}
334-
335-
@Override
336-
public HV getValue() {
337-
return deserializeHashValue(source.getValue());
338-
}
339-
340-
@Override
341-
public HV setValue(HV value) {
342-
throw new UnsupportedOperationException("Values cannot be set when scanning through entries.");
343-
}
344-
};
327+
return Converters.entryOf(deserializeHashKey(source.getKey()), deserializeHashValue(source.getValue()));
345328
}
346329
}));
347330

src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.redis.core;
1717

18+
import org.springframework.data.redis.connection.convert.Converters;
1819
import reactor.core.publisher.Flux;
1920
import reactor.core.publisher.Mono;
2021

@@ -149,7 +150,7 @@ public Mono<Double> increment(H key, HK hashKey, double delta) {
149150
* @see org.springframework.data.redis.core.ReactiveHashOperations#randomField(H)
150151
*/
151152
@Override
152-
public Mono<HK> randomField(H key) {
153+
public Mono<HK> randomKey(H key) {
153154

154155
Assert.notNull(key, "Key must not be null!");
155156

@@ -162,7 +163,7 @@ public Mono<HK> randomField(H key) {
162163
* @see org.springframework.data.redis.core.ReactiveHashOperations#randomValue(H)
163164
*/
164165
@Override
165-
public Mono<Map.Entry<HK, HV>> randomValue(H key) {
166+
public Mono<Map.Entry<HK, HV>> randomEntry(H key) {
166167

167168
Assert.notNull(key, "Key must not be null!");
168169

@@ -175,7 +176,7 @@ public Mono<Map.Entry<HK, HV>> randomValue(H key) {
175176
* @see org.springframework.data.redis.core.ReactiveHashOperations#randomFields(H, long)
176177
*/
177178
@Override
178-
public Flux<HK> randomFields(H key, long count) {
179+
public Flux<HK> randomKeys(H key, long count) {
179180

180181
Assert.notNull(key, "Key must not be null!");
181182

@@ -188,7 +189,7 @@ public Flux<HK> randomFields(H key, long count) {
188189
* @see org.springframework.data.redis.core.ReactiveHashOperations#randomValues(H, long)
189190
*/
190191
@Override
191-
public Flux<Map.Entry<HK, HV>> randomValues(H key, long count) {
192+
public Flux<Map.Entry<HK, HV>> randomEntries(H key, long count) {
192193

193194
Assert.notNull(key, "Key must not be null!");
194195

@@ -353,8 +354,7 @@ private HV readHashValue(ByteBuffer value) {
353354
}
354355

355356
private Map.Entry<HK, HV> deserializeHashEntry(Map.Entry<ByteBuffer, ByteBuffer> source) {
356-
return Collections.singletonMap(readHashKey(source.getKey()), readHashValue(source.getValue())).entrySet()
357-
.iterator().next();
357+
return Converters.entryOf(readHashKey(source.getKey()), readHashValue(source.getValue()));
358358
}
359359

360360
private List<HV> deserializeHashValues(List<ByteBuffer> source) {

src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.redis.core;
1717

18+
import org.springframework.data.redis.connection.convert.Converters;
1819
import reactor.core.publisher.Flux;
1920
import reactor.core.publisher.Mono;
2021

@@ -422,8 +423,7 @@ public MapRecord<K, HK, HV> deserializeRecord(ByteBufferRecord record) {
422423
}
423424

424425
private Entry<HK, HV> deserializeRecordFields(Entry<ByteBuffer, ByteBuffer> it) {
425-
return Collections.singletonMap(readHashKey(it.getKey()), deserializeHashValue(it.getValue())).entrySet().iterator()
426-
.next();
426+
return Converters.entryOf(readHashKey(it.getKey()), deserializeHashValue(it.getValue()));
427427
}
428428

429429
private ByteBufferRecord serializeRecord(MapRecord<K, ? extends HK, ? extends HV> record) {
@@ -432,6 +432,6 @@ private ByteBufferRecord serializeRecord(MapRecord<K, ? extends HK, ? extends HV
432432
}
433433

434434
private Entry<ByteBuffer, ByteBuffer> serializeRecordFields(Entry<? extends HK, ? extends HV> it) {
435-
return Collections.singletonMap(rawHashKey(it.getKey()), rawValue(it.getValue())).entrySet().iterator().next();
435+
return Converters.entryOf(rawHashKey(it.getKey()), rawValue(it.getValue()));
436436
}
437437
}

src/main/java/org/springframework/data/redis/core/HashOperations.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -89,31 +89,31 @@ public interface HashOperations<H, HK, HV> {
8989
Double increment(H key, HK hashKey, double delta);
9090

9191
/**
92-
* Return a random field from the hash value stored at {@code key}.
92+
* Return a random hash key (aka field) from the hash value stored at {@code key}.
9393
*
9494
* @param key must not be {@literal null}.
9595
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
9696
* @since 2.6
9797
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
9898
*/
9999
@Nullable
100-
HK randomField(H key);
100+
HK randomKey(H key);
101101

102102
/**
103-
* Return a random field from the hash value stored at {@code key}.
103+
* Return a random entry from the hash value stored at {@code key}.
104104
*
105105
* @param key must not be {@literal null}.
106106
* @return {@literal null} if key does not exist or when used in pipeline / transaction.
107107
* @since 2.6
108108
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
109109
*/
110110
@Nullable
111-
Map.Entry<HK, HV> randomValue(H key);
111+
Map.Entry<HK, HV> randomEntry(H key);
112112

113113
/**
114-
* Return a random field from the hash value stored at {@code key}. If the provided {@code count} argument is
115-
* positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is
116-
* negative, the behavior changes and the command is allowed to return the same field multiple times. In this case,
114+
* Return random hash keys (aka fields) from the hash value stored at {@code key}. If the provided {@code count} argument is
115+
* positive, return a list of distinct hash keys, capped either at {@code count} or the hash size. If {@code count} is
116+
* negative, the behavior changes and the command is allowed to return the same hash key multiple times. In this case,
117117
* the number of returned fields is the absolute value of the specified count.
118118
*
119119
* @param key must not be {@literal null}.
@@ -123,10 +123,10 @@ public interface HashOperations<H, HK, HV> {
123123
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
124124
*/
125125
@Nullable
126-
List<HK> randomFields(H key, long count);
126+
List<HK> randomKeys(H key, long count);
127127

128128
/**
129-
* Return a random field from the hash value stored at {@code key}.
129+
* Return a random entries from the hash value stored at {@code key}.
130130
*
131131
* @param key must not be {@literal null}.
132132
* @param count number of fields to return. Must be positive.
@@ -135,7 +135,7 @@ public interface HashOperations<H, HK, HV> {
135135
* @see <a href="https://redis.io/commands/hrandfield">Redis Documentation: HRANDFIELD</a>
136136
*/
137137
@Nullable
138-
Map<HK, HV> randomValues(H key, long count);
138+
Map<HK, HV> randomEntries(H key, long count);
139139

140140
/**
141141
* Get key set (fields) of hash at {@code key}.

0 commit comments

Comments
 (0)