diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 89962ad55..40dffba45 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -108,23 +108,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco private boolean deserializePipelineAndTxResults = false; private Entry convertEntry(Entry source) { - return new Entry() { - - @Override - public String getKey() { - return bytesToString.convert(source.getKey()); - } - - @Override - public String getValue() { - return bytesToString.convert(source.getValue()); - } - - @Override - public String setValue(String value) { - throw new UnsupportedOperationException("Cannot set value for entry"); - } - }; + return Converters.entryOf(bytesToString.convert(source.getKey()), bytesToString.convert(source.getValue())); } private class DeserializingConverter implements Converter { diff --git a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java index 80fc7dbe1..604fcbc49 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java @@ -18,16 +18,7 @@ package org.springframework.data.redis.connection.convert; import java.io.StringReader; import java.nio.ByteBuffer; import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; @@ -472,7 +463,7 @@ abstract public class Converters { * @since 2.6 */ public static Map.Entry entryOf(K key, V value) { - return new SimpleEntry<>(key, value); + return new AbstractMap.SimpleImmutableEntry<>(key, value); } /** @@ -653,30 +644,4 @@ abstract public class Converters { } } - - private static class SimpleEntry implements Map.Entry { - - private final K key; - private final V value; - - public SimpleEntry(K key, V value) { - this.key = key; - this.value = value; - } - - @Override - public K getKey() { - return key; - } - - @Override - public V getValue() { - return value; - } - - @Override - public V setValue(V value) { - throw new UnsupportedOperationException(); - } - } } diff --git a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java index 47ce81ca5..7f29d359d 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java @@ -89,49 +89,49 @@ public interface BoundHashOperations extends BoundKeyOperations { Double increment(HK key, double delta); /** - * Return a random field from the hash value stored at the bound key. + * Return a random key (aka field) from the hash value stored at the bound key. * - * @return {@literal null} if key does not exist or when used in pipeline / transaction. + * @return {@literal null} if the hash does not exist or when used in pipeline / transaction. * @since 2.6 * @see Redis Documentation: HRANDFIELD */ @Nullable - HK randomField(); + HK randomKey(); /** - * Return a random field from the hash value stored at the bound key. + * Return a random entry from the hash value stored at the bound key. * * @return {@literal null} if key does not exist or when used in pipeline / transaction. * @since 2.6 * @see Redis Documentation: HRANDFIELD */ @Nullable - Map.Entry randomValue(); + Map.Entry randomEntry(); /** - * Return a random field from the hash value stored at the bound key. If the provided {@code count} argument is - * positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is - * negative, the behavior changes and the command is allowed to return the same field multiple times. In this case, - * the number of returned fields is the absolute value of the specified count. + * Return a random keys (aka fields) from the hash value stored at the bound key. If the provided {@code count} argument is + * positive, return a list of distinct keys, capped either at {@code count} or the hash size. If {@code count} is + * negative, the behavior changes and the command is allowed to return the same key multiple times. In this case, + * the number of returned keys is the absolute value of the specified count. * - * @param count number of fields to return. + * @param count number of keys to return. * @return {@literal null} if key does not exist or when used in pipeline / transaction. * @since 2.6 * @see Redis Documentation: HRANDFIELD */ @Nullable - List randomFields(long count); + List randomKeys(long count); /** - * Return a random field from the hash value stored at the bound key. + * Return a random entry from the hash value stored at the bound key. * - * @param count number of fields to return. Must be positive. - * @return {@literal null} if key does not exist or when used in pipeline / transaction. + * @param count number of entries to return. Must be positive. + * @return {@literal null} if the hash does not exist or when used in pipeline / transaction. * @since 2.6 * @see Redis Documentation: HRANDFIELD */ @Nullable - Map randomValues(long count); + Map randomEntries(long count); /** * Get key set (fields) of hash at the bound key. diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java index 0493c294e..fcab7066f 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java @@ -116,8 +116,8 @@ class DefaultBoundHashOperations extends DefaultBoundKeyOperations */ @Nullable @Override - public HK randomField() { - return ops.randomField(getKey()); + public HK randomKey() { + return ops.randomKey(getKey()); } /* @@ -126,8 +126,8 @@ class DefaultBoundHashOperations extends DefaultBoundKeyOperations */ @Nullable @Override - public Entry randomValue() { - return ops.randomValue(getKey()); + public Entry randomEntry() { + return ops.randomEntry(getKey()); } /* @@ -136,8 +136,8 @@ class DefaultBoundHashOperations extends DefaultBoundKeyOperations */ @Nullable @Override - public List randomFields(long count) { - return ops.randomFields(getKey(), count); + public List randomKeys(long count) { + return ops.randomKeys(getKey(), count); } /* @@ -146,8 +146,8 @@ class DefaultBoundHashOperations extends DefaultBoundKeyOperations */ @Nullable @Override - public Map randomValues(long count) { - return ops.randomValues(getKey(), count); + public Map randomEntries(long count) { + return ops.randomEntries(getKey(), count); } /* diff --git a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java index dc096ffb8..45f493630 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java @@ -99,7 +99,7 @@ class DefaultHashOperations extends AbstractOperations imp */ @Nullable @Override - public HK randomField(K key) { + public HK randomKey(K key) { byte[] rawKey = rawKey(key); return deserializeHashKey(execute(connection -> connection.hRandField(rawKey), true)); @@ -111,7 +111,7 @@ class DefaultHashOperations extends AbstractOperations imp */ @Nullable @Override - public Entry randomValue(K key) { + public Entry randomEntry(K key) { byte[] rawKey = rawKey(key); Entry rawEntry = execute(connection -> connection.hRandFieldWithValues(rawKey), true); @@ -125,7 +125,7 @@ class DefaultHashOperations extends AbstractOperations imp */ @Nullable @Override - public List randomFields(K key, long count) { + public List randomKeys(K key, long count) { byte[] rawKey = rawKey(key); List rawValues = execute(connection -> connection.hRandField(rawKey, count), true); @@ -138,7 +138,7 @@ class DefaultHashOperations extends AbstractOperations imp */ @Nullable @Override - public Map randomValues(K key, long count) { + public Map randomEntries(K key, long count) { Assert.isTrue(count > 0, "Count must not be negative"); byte[] rawKey = rawKey(key); @@ -324,24 +324,7 @@ class DefaultHashOperations extends AbstractOperations imp @Override public Entry convert(final Entry source) { - - return new Entry() { - - @Override - public HK getKey() { - return deserializeHashKey(source.getKey()); - } - - @Override - public HV getValue() { - return deserializeHashValue(source.getValue()); - } - - @Override - public HV setValue(HV value) { - throw new UnsupportedOperationException("Values cannot be set when scanning through entries."); - } - }; + return Converters.entryOf(deserializeHashKey(source.getKey()), deserializeHashValue(source.getValue())); } })); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java index a2fa529d5..08b3ba083 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.data.redis.connection.convert.Converters; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -149,7 +150,7 @@ class DefaultReactiveHashOperations implements ReactiveHashOperations * @see org.springframework.data.redis.core.ReactiveHashOperations#randomField(H) */ @Override - public Mono randomField(H key) { + public Mono randomKey(H key) { Assert.notNull(key, "Key must not be null!"); @@ -162,7 +163,7 @@ class DefaultReactiveHashOperations implements ReactiveHashOperations * @see org.springframework.data.redis.core.ReactiveHashOperations#randomValue(H) */ @Override - public Mono> randomValue(H key) { + public Mono> randomEntry(H key) { Assert.notNull(key, "Key must not be null!"); @@ -175,7 +176,7 @@ class DefaultReactiveHashOperations implements ReactiveHashOperations * @see org.springframework.data.redis.core.ReactiveHashOperations#randomFields(H, long) */ @Override - public Flux randomFields(H key, long count) { + public Flux randomKeys(H key, long count) { Assert.notNull(key, "Key must not be null!"); @@ -188,7 +189,7 @@ class DefaultReactiveHashOperations implements ReactiveHashOperations * @see org.springframework.data.redis.core.ReactiveHashOperations#randomValues(H, long) */ @Override - public Flux> randomValues(H key, long count) { + public Flux> randomEntries(H key, long count) { Assert.notNull(key, "Key must not be null!"); @@ -353,8 +354,7 @@ class DefaultReactiveHashOperations implements ReactiveHashOperations } private Map.Entry deserializeHashEntry(Map.Entry source) { - return Collections.singletonMap(readHashKey(source.getKey()), readHashValue(source.getValue())).entrySet() - .iterator().next(); + return Converters.entryOf(readHashKey(source.getKey()), readHashValue(source.getValue())); } private List deserializeHashValues(List source) { diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java index 6a95cec50..0fc811c99 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.data.redis.connection.convert.Converters; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -422,8 +423,7 @@ class DefaultReactiveStreamOperations implements ReactiveStreamOperat } private Entry deserializeRecordFields(Entry it) { - return Collections.singletonMap(readHashKey(it.getKey()), deserializeHashValue(it.getValue())).entrySet().iterator() - .next(); + return Converters.entryOf(readHashKey(it.getKey()), deserializeHashValue(it.getValue())); } private ByteBufferRecord serializeRecord(MapRecord record) { @@ -432,6 +432,6 @@ class DefaultReactiveStreamOperations implements ReactiveStreamOperat } private Entry serializeRecordFields(Entry it) { - return Collections.singletonMap(rawHashKey(it.getKey()), rawValue(it.getValue())).entrySet().iterator().next(); + return Converters.entryOf(rawHashKey(it.getKey()), rawValue(it.getValue())); } } diff --git a/src/main/java/org/springframework/data/redis/core/HashOperations.java b/src/main/java/org/springframework/data/redis/core/HashOperations.java index 60b763e16..fac681758 100644 --- a/src/main/java/org/springframework/data/redis/core/HashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/HashOperations.java @@ -89,7 +89,7 @@ public interface HashOperations { Double increment(H key, HK hashKey, double delta); /** - * Return a random field from the hash value stored at {@code key}. + * Return a random hash key (aka field) from the hash value stored at {@code key}. * * @param key must not be {@literal null}. * @return {@literal null} if key does not exist or when used in pipeline / transaction. @@ -97,10 +97,10 @@ public interface HashOperations { * @see Redis Documentation: HRANDFIELD */ @Nullable - HK randomField(H key); + HK randomKey(H key); /** - * Return a random field from the hash value stored at {@code key}. + * Return a random entry from the hash value stored at {@code key}. * * @param key must not be {@literal null}. * @return {@literal null} if key does not exist or when used in pipeline / transaction. @@ -108,12 +108,12 @@ public interface HashOperations { * @see Redis Documentation: HRANDFIELD */ @Nullable - Map.Entry randomValue(H key); + Map.Entry randomEntry(H key); /** - * Return a random field from the hash value stored at {@code key}. If the provided {@code count} argument is - * positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is - * negative, the behavior changes and the command is allowed to return the same field multiple times. In this case, + * Return random hash keys (aka fields) from the hash value stored at {@code key}. If the provided {@code count} argument is + * positive, return a list of distinct hash keys, capped either at {@code count} or the hash size. If {@code count} is + * negative, the behavior changes and the command is allowed to return the same hash key multiple times. In this case, * the number of returned fields is the absolute value of the specified count. * * @param key must not be {@literal null}. @@ -123,10 +123,10 @@ public interface HashOperations { * @see Redis Documentation: HRANDFIELD */ @Nullable - List randomFields(H key, long count); + List randomKeys(H key, long count); /** - * Return a random field from the hash value stored at {@code key}. + * Return a random entries from the hash value stored at {@code key}. * * @param key must not be {@literal null}. * @param count number of fields to return. Must be positive. @@ -135,7 +135,7 @@ public interface HashOperations { * @see Redis Documentation: HRANDFIELD */ @Nullable - Map randomValues(H key, long count); + Map randomEntries(H key, long count); /** * Get key set (fields) of hash at {@code key}. diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveHashOperations.java b/src/main/java/org/springframework/data/redis/core/ReactiveHashOperations.java index 562f6647d..da550099f 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveHashOperations.java @@ -88,29 +88,29 @@ public interface ReactiveHashOperations { Mono increment(H key, HK hashKey, double delta); /** - * Return a random field from the hash value stored at {@code key}. + * Return a random hash key (aka field) from the hash value stored at {@code key}. * * @param key must not be {@literal null}. * @return * @since 2.6 * @see Redis Documentation: HRANDFIELD */ - Mono randomField(H key); + Mono randomKey(H key); /** - * Return a random field from the hash value stored at {@code key}. + * Return a random entry from the hash value stored at {@code key}. * * @param key must not be {@literal null}. * @return * @since 2.6 * @see Redis Documentation: HRANDFIELD */ - Mono> randomValue(H key); + Mono> randomEntry(H key); /** - * Return a random field from the hash value stored at {@code key}. If the provided {@code count} argument is - * positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is - * negative, the behavior changes and the command is allowed to return the same field multiple times. In this case, + * Return random hash keys (aka fields) from the hash value stored at {@code key}. If the provided {@code count} argument is + * positive, return a list of distinct hash keys, capped either at {@code count} or the hash size. If {@code count} is + * negative, the behavior changes and the command is allowed to return the same hash key multiple times. In this case, * the number of returned fields is the absolute value of the specified count. * * @param key must not be {@literal null}. @@ -119,12 +119,12 @@ public interface ReactiveHashOperations { * @since 2.6 * @see Redis Documentation: HRANDFIELD */ - Flux randomFields(H key, long count); + Flux randomKeys(H key, long count); /** - * Return a random field from the hash value stored at {@code key}. If the provided {@code count} argument is - * positive, return a list of distinct fields, capped either at {@code count} or the hash size. If {@code count} is - * negative, the behavior changes and the command is allowed to return the same field multiple times. In this case, + * Return random entries from the hash stored at {@code key}. If the provided {@code count} argument is + * positive, return a list of distinct entries, capped either at {@code count} or the hash size. If {@code count} is + * negative, the behavior changes and the command is allowed to return the same entry multiple times. In this case, * the number of returned fields is the absolute value of the specified count. * * @param key must not be {@literal null}. @@ -133,7 +133,7 @@ public interface ReactiveHashOperations { * @since 2.6 * @see Redis Documentation: HRANDFIELD */ - Flux> randomValues(H key, long count); + Flux> randomEntries(H key, long count); /** * Get key set (fields) of hash at {@code key}. diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java index fbc41c6fb..e32120473 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java @@ -81,6 +81,24 @@ public class DefaultRedisMap implements RedisMap { return hashOps.increment(key, delta); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.support.collections.RedisMap#randomKey() + */ + @Override + public K randomKey() { + return hashOps.randomKey(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.support.collections.RedisMap#randomEntry() + */ + @Override + public Entry randomEntry() { + return hashOps.randomEntry(); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.support.collections.RedisStore#getOperations() diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java b/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java index 3fff2aba9..696aea272 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java @@ -19,6 +19,8 @@ import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentMap; +import org.springframework.lang.Nullable; + /** * Map view of a Redis hash. * @@ -27,10 +29,43 @@ import java.util.concurrent.ConcurrentMap; */ public interface RedisMap extends RedisStore, ConcurrentMap { + /** + * Increment {@code value} of the hash {@code key} by the given {@code delta}. + * + * @param key must not be {@literal null}. + * @param delta + * @return {@literal null} if hash does not exist. + * @since 1.0 + */ Long increment(K key, long delta); + /** + * Increment {@code value} of the hash {@code key} by the given {@code delta}. + * + * @param key must not be {@literal null}. + * @param delta + * @return {@literal null} if hash does not exist. + * @since 1.1 + */ Double increment(K key, double delta); + /** + * Get a random key from the hash. + * + * @return {@literal null} if the hash does not exist. + * @since 2.6 + */ + K randomKey(); + + /** + * Get a random entry from the hash. + * + * @return {@literal null} if the hash does not exist. + * @since 2.6 + */ + @Nullable + Map.Entry randomEntry(); + /** * @since 1.4 * @return diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java b/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java index 9dd7fc1c6..04614026b 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java @@ -304,6 +304,24 @@ public class RedisProperties extends Properties implements RedisMap randomEntry() { + return (Entry) delegate.randomEntry(); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.support.collections.RedisStore#getOperations() diff --git a/src/test/java/org/springframework/data/redis/core/DefaultHashOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultHashOperationsIntegrationTests.java index d023f082d..7d6bf4359 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultHashOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultHashOperationsIntegrationTests.java @@ -173,8 +173,8 @@ public class DefaultHashOperationsIntegrationTests { hashOps.put(key, key1, val1); hashOps.put(key, key2, val2); - assertThat(hashOps.randomField(key)).isIn(key1, key2); - assertThat(hashOps.randomFields(key, 2)).hasSize(2).contains(key1, key2); + assertThat(hashOps.randomKey(key)).isIn(key1, key2); + assertThat(hashOps.randomKeys(key, 2)).hasSize(2).contains(key1, key2); } @ParameterizedRedisTest // GH-2048 @@ -190,7 +190,7 @@ public class DefaultHashOperationsIntegrationTests { hashOps.put(key, key1, val1); hashOps.put(key, key2, val2); - Map.Entry entry = hashOps.randomValue(key); + Map.Entry entry = hashOps.randomEntry(key); if (entry.getKey().equals(key1)) { assertThat(entry.getValue()).isEqualTo(val1); @@ -198,7 +198,7 @@ public class DefaultHashOperationsIntegrationTests { assertThat(entry.getValue()).isEqualTo(val2); } - Map values = hashOps.randomValues(key, 10); + Map values = hashOps.randomEntries(key, 10); assertThat(values).hasSize(2).containsEntry(key1, val1).containsEntry(key2, val2); } } diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java index 171e6ec1e..9c714b422 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java @@ -18,11 +18,11 @@ package org.springframework.data.redis.core; import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assumptions.*; +import org.springframework.data.redis.connection.convert.Converters; import reactor.test.StepVerifier; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -251,13 +251,13 @@ public class DefaultReactiveHashOperationsIntegrationTests { .expectNext(true) // .verifyComplete(); - hashOperations.randomField(key) // + hashOperations.randomKey(key) // .as(StepVerifier::create) // .assertNext(actual -> { assertThat(actual).isIn(hashkey1, hashkey2); }).verifyComplete(); - hashOperations.randomFields(key, -10) // + hashOperations.randomKeys(key, -10) // .collectList().as(StepVerifier::create) // .assertNext(actual -> { assertThat(actual).hasSize(10); @@ -286,7 +286,7 @@ public class DefaultReactiveHashOperationsIntegrationTests { .expectNext(true) // .verifyComplete(); - hashOperations.randomValue(key) // + hashOperations.randomEntry(key) // .as(StepVerifier::create) // .assertNext(actual -> { @@ -297,7 +297,7 @@ public class DefaultReactiveHashOperationsIntegrationTests { } }).verifyComplete(); - hashOperations.randomValues(key, -10) // + hashOperations.randomEntries(key, -10) // .collectList().as(StepVerifier::create) // .assertNext(actual -> { assertThat(actual).hasSize(10); @@ -462,8 +462,8 @@ public class DefaultReactiveHashOperationsIntegrationTests { .as(StepVerifier::create) // .consumeNextWith(list -> { - Entry entry1 = Collections.singletonMap(hashkey1, hashvalue1).entrySet().iterator().next(); - Entry entry2 = Collections.singletonMap(hashkey2, hashvalue2).entrySet().iterator().next(); + Entry entry1 = Converters.entryOf(hashkey1, hashvalue1); + Entry entry2 = Converters.entryOf(hashkey2, hashvalue2); assertThat(list).containsExactlyInAnyOrder(entry1, entry2); }) // @@ -489,8 +489,8 @@ public class DefaultReactiveHashOperationsIntegrationTests { .as(StepVerifier::create) // .consumeNextWith(list -> { - Entry entry1 = Collections.singletonMap(hashkey1, hashvalue1).entrySet().iterator().next(); - Entry entry2 = Collections.singletonMap(hashkey2, hashvalue2).entrySet().iterator().next(); + Entry entry1 = Converters.entryOf(hashkey1, hashvalue1); + Entry entry2 = Converters.entryOf(hashkey2, hashvalue2); assertThat(list).containsExactlyInAnyOrder(entry1, entry2); }) // diff --git a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapIntegrationTests.java b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapIntegrationTests.java index 4ae49dcc6..dc1472c8b 100644 --- a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapIntegrationTests.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assumptions.*; import java.io.IOException; import java.text.DecimalFormat; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; @@ -28,17 +29,19 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.assertj.core.api.Assumptions; import org.junit.jupiter.api.BeforeEach; - import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.DoubleAsStringObjectFactory; import org.springframework.data.redis.LongAsStringObjectFactory; import org.springframework.data.redis.ObjectFactory; +import org.springframework.data.redis.RawObjectFactory; import org.springframework.data.redis.RedisSystemException; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.test.condition.EnabledOnCommand; import org.springframework.data.redis.test.extension.parametrized.MethodSource; import org.springframework.data.redis.test.extension.parametrized.ParameterizedRedisTest; @@ -458,4 +461,39 @@ public abstract class AbstractRedisMapIntegrationTests { } cursor.close(); } + + @ParameterizedRedisTest // GH-2048 + @EnabledOnCommand("HRANDFIELD") + public void randomKeyFromHash() { + + K k1 = getKey(); + K k2 = getKey(); + + V v1 = getValue(); + V v2 = getValue(); + + map.put(k1, v1); + map.put(k2, v2); + + assertThat(map.randomKey()).isIn(k1, k2); + } + + @ParameterizedRedisTest // GH-2048 + @EnabledOnCommand("HRANDFIELD") + public void randomEntryFromHash() { + + Assumptions.assumeThat(this.valueFactory).isNotInstanceOf(RawObjectFactory.class); + + K k1 = getKey(); + K k2 = getKey(); + + V v1 = getValue(); + V v2 = getValue(); + + map.put(k1, v1); + map.put(k2, v2); + + assertThat(map.randomEntry()).isIn(new AbstractMap.SimpleImmutableEntry(k1, v1), + new AbstractMap.SimpleImmutableEntry(k2, v2)); + } }