SetOperations 操作接口定义了怎样操作 Redis 的 set 类型。在 RedisTemplate 中,可以通过 opsForSet() 方法获取该操作接口。代码如下:
SetOperations<String,String> ops = redisTemplate.opsForSet();
使用 add() 方法可以将一个或多个值设置给键的集合。方法定义如下:
Long add(K key, V... values) 将给定的一个或多个值设置给指定的键
示例:
SetOperations<String,String> ops = redisTemplate.opsForSet(); // 设置多个值给 set-key 键 ops.add("set-key", "value1", "value2", "value3"); // 获取 set-key 键的值 Set<String> values = ops.members("set-key"); System.out.println("set-key=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
set-key=[value2, value3, value1]
使用 members() 方法获取指定键的所有值,方法定义如下:
Set<V> members(K key) 将返回指定键的所有值
具体用法,请参考 add() 方法。
使用 pop() 方法可以从指定键中随机移除且返回元素。方法定义如下:
V pop(K key) 从键的集合中随机移除并返回一个成员
List<V> pop(K key, long count) 从键的集合中随机删除并返回 count 个成员
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 设置多个值给 set-key 键 ops.add("set-key", "value1", "value2", "value3", "value4", "value5"); // 随机返回一个 String val = ops.pop("set-key"); System.out.println("val=" + val); values = ops.members("set-key"); System.out.println("set-key=" + Arrays.toString(values.toArray())); // 随机返回多个 List<String> vals = ops.pop("set-key", 3); System.out.println("vals=" + Arrays.toString(vals.toArray())); values = ops.members("set-key"); System.out.println("set-key=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
val=value4 set-key=[value2, value1, value5, value3] vals=[value5, value3, value1] set-key=[value2]
注意:如果执行 ops(key, count) 方法时,Redis 版本为 3,则会抛出如下错误:org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR wrong number of arguments for 'spop' command。
上面错误的主要原因是 Redis 版本太低了,这个命令后面才支持,建议升级到 3.2 及以后,见 https://github.com/redis/jedis/issues/1247。
使用 intersect() 方法可以计算两个集合,或者多个集合跟某个集合的交集。方法定义如下:
Set<V> intersect(K key, Collection<K> otherKeys) 获取 key 和所有 otherKeys 集合中键的交集
Set<V> intersect(K key, K otherKey) 获取 key 和 otherKey 对应集合间的交集
Long intersectAndStore(K key, Collection<K> otherKeys, K destKey) 获取 key 和所有 otherKeys 集合中键的交集,并将结果存储在 destKey 键中。
Long intersectAndStore(K key, K otherKey, K destKey) 获取 key 和 otherKey 对应集合间的交集,并将结果存储在 destKey 键中。
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key1", "value1", "value2", "value3"); ops.add("set-key2", "value2", "value3", "value4"); ops.add("set-key3", "value3", "value4", "value5"); values = ops.members("set-key1"); System.out.println("set-key1=" + Arrays.toString(values.toArray())); values = ops.members("set-key2"); System.out.println("set-key2=" + Arrays.toString(values.toArray())); values = ops.members("set-key3"); System.out.println("set-key3=" + Arrays.toString(values.toArray())); // 获取 set-key1 和 set-key2 集合的交集(即在两个集合中均存在的元素) values = ops.intersect("set-key1", "set-key2"); System.out.println("intersect=" + Arrays.toString(values.toArray())); // 获取 set-key1、set-key2 和 set-key3 集合的交集 values = ops.intersect("set-key1", Arrays.asList("set-key2", "set-key3")); System.out.println("intersect=" + Arrays.toString(values.toArray())); // 获取 set-key1、set-key2 和 set-key3 集合的交集,并将结果存储到 set-result 中 ops.intersectAndStore("set-key1", Arrays.asList("set-key2", "set-key3"), "set-result"); values = ops.members("set-result"); System.out.println("intersect=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
set-key1=[value2, value3, value1] set-key2=[value4, value2, value3] set-key3=[value4, value5, value3] intersect=[value2, value3] intersect=[value3] intersect=[value3]
使用 difference() 方法计算指定两个或多个集合的差异。方法定义如下:
Set<V> difference(K key, Collection<K> otherKeys) 计算 key 和 otherKeys 集合的差异,返回 key 集合中所有没有在 otherKeys 所有集合中出现的元素集合。
Set<V> difference(K key, K otherKey) 计算 key 和 otherKey 集合的差异,返回 key 集合中所有没有在 otherKey 集合中出现的元素集合。
Long differenceAndStore(K key, Collection<K> otherKeys, K destKey) 计算 key 和 otherKeys 集合的差异,返回 key 集合中所有没有在 otherKeys 所有集合中出现的元素集合。并且将计算结果保存到 destKey 中。
Long differenceAndStore(K key, K otherKey, K destKey) 计算 key 和 otherKey 集合的差异,返回 key 集合中所有没有在 otherKey 集合中出现的元素集合。并且将计算结果保存到 destKey 中。
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key1", "value1", "value2", "value3"); ops.add("set-key2", "value3"); ops.add("set-key3", "value2"); values = ops.members("set-key1"); System.out.println("set-key1=" + Arrays.toString(values.toArray())); values = ops.members("set-key2"); System.out.println("set-key2=" + Arrays.toString(values.toArray())); values = ops.members("set-key3"); System.out.println("set-key3=" + Arrays.toString(values.toArray())); // 获取 set-key1 集合中没有在 set-key2 集合中的元素 values = ops.difference("set-key1", "set-key2"); System.out.println("values=" + Arrays.toString(values.toArray())); // 获取 set-key1 集合中没有在 set-key2 或 set-key3 集合中的元素 values = ops.difference("set-key1", Arrays.asList("set-key2", "set-key3")); System.out.println("values=" + Arrays.toString(values.toArray())); // 获取 set-key1 集合中没有在 set-key2 或 set-key3 集合中的元素, // 且将结果存储到 set-result 键 ops.differenceAndStore("set-key1", Arrays.asList("set-key2", "set-key3"), "set-result"); values = ops.members("set-result"); System.out.println("values=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
set-key1=[value1, value2, value3] set-key2=[value3] set-key3=[value2] values=[value1, value2] values=[value1] values=[value1]
使用 union() 方法可以计算多个集合的并集,方法定义如下:
Set<V> union(K key, Collection<K> otherKeys) 获取 key 和 otherKeys 多个集合的并集
Set<V> union(K key, K otherKey) 获取 key 和 otherKey 两个集合的并集
Long unionAndStore(K key, Collection<K> otherKeys, K destKey) 获取 key 和 otherKeys 多个集合的并集,并且将结果存储到 destKey 集合
Long unionAndStore(K key, K otherKey, K destKey) 获取 key 和 otherKey 两个集合的并集,并且将结果存储到 destKey 集合
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key1", "value1", "value2", "value3"); ops.add("set-key2", "value3", "value4"); ops.add("set-key3", "value5"); values = ops.members("set-key1"); System.out.println("set-key1=" + Arrays.toString(values.toArray())); values = ops.members("set-key2"); System.out.println("set-key2=" + Arrays.toString(values.toArray())); values = ops.members("set-key3"); System.out.println("set-key3=" + Arrays.toString(values.toArray())); // 获取 set-key1 和 set-key2 集合的并集 values = ops.union("set-key1", "set-key2"); System.out.println("values=" + Arrays.toString(values.toArray())); // 获取 set-key1、set-key2 和 set-key3 集合的并集 values = ops.union("set-key1", Arrays.asList("set-key2", "set-key3")); System.out.println("values=" + Arrays.toString(values.toArray())); // 获取 set-key1 和 set-key2 集合的并集,并且存储到 set-result 集合 ops.unionAndStore("set-key1", "set-key2", "set-result"); values = ops.members("set-result"); System.out.println("values=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
set-key1=[value2, value1, value3] set-key2=[value4, value3] set-key3=[value5] values=[value2, value1, value4, value3] values=[value1, value4, value3, value2, value5] values=[value2, value1, value4, value3]
使用 randomMember() 方法可以从集合中随机返回一个或多个元素,方法定义如下:
V randomMember(K key) 从键的集合中随机返回一个元素
List<V> randomMembers(K key, long count) 从键的集合中随机返回 count 个元素
Set<V> distinctRandomMembers(K key, long count) 从键的集合中随机返回 count 个不重复的元素
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据(set 集合不能重复) ops.add("set-key", "value1", "value2", "value3", "value4", "value5", "value1", "value2", "value3", "value4", "value5"); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray())); // 从键集合中随机返回一个元素 String randomVal = ops.randomMember("set-key"); System.out.println("randomVal=" + randomVal); // 从键集合中随机返回3个元素 List<String> randomVals = ops.randomMembers("set-key", 3); System.out.println("randomVals=" + Arrays.toString(randomVals.toArray())); // 从键集合中随机返回3个元素,但是不能有重复元素 // 这个操作在 set 集合中没有实际作用,因为 set 集合不允许重复元素 values = ops.distinctRandomMembers("set-key", 3); System.out.println("randomVals=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
values=[value2, value5, value3, value1, value4] randomVal=value2 randomVals=[value5, value2, value1] randomVals=[value1, value2, value4]
使用 isMember() 方法判断指定的键是否存在某个元素,方法定义如下:
Boolean isMember(K key, Object o) 检查 key 的集合中是否存在 o 元素。
示例:
Boolean flag; Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key", "value1", "value2", "value3", "value4"); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray())); // 判断元素 value1 是否在 set-key 集合中存在 flag = ops.isMember("set-key", "value1"); System.out.println("Does value1 exist? " + flag); flag = ops.isMember("set-key", "value5"); System.out.println("Does value5 exist? " + flag);
运行示例,输出结果:
values=[value2, value1, value4, value3] Does value1 exist? true Does value5 exist? false
使用 move() 方法可以将一个元素从一个集合移动到另一个集合。方法定义如下:
Boolean move(K key, V value, K destKey) 将 value 从 key 移动到 destKey 集合
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key", "value1", "value2", "value3", "value4"); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray())); // 将 value2 移动到 set-key2 集合 Boolean flag = ops.move("set-key", "value2", "set-key2"); if(flag) { System.out.println("Move successfully."); } values = ops.members("set-key2"); System.out.println("set-key2=" + Arrays.toString(values.toArray())); values = ops.members("set-key"); System.out.println("set-key=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
values=[value2, value1, value4, value3] Move successfully. set-key2=[value2] set-key=[value1, value4, value3]
使用 remove() 方法可以从指定键的集合中移除一个或多个元素,方法定义如下:
Long remove(K key, Object... values) 从 key 的集合中移除 values 元素,且返回移除元素的数量
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key", "value1", "value2", "value3", "value4"); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray())); // 移除多个元素 Long size = ops.remove("set-key", "value2", "value4", "value6"); System.out.println("size=" + size); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
values=[value2, value1, value4, value3] size=2 values=[value1, value3]
使用 size() 方法可以返回指定键的集合的大小,方法定义如下:
Long size(K key) 获取指定键的集合大小
示例:
Set<String> values; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 ops.add("set-key", "value1", "value2", "value3", "value4"); values = ops.members("set-key"); System.out.println("values=" + Arrays.toString(values.toArray())); // 获取集合大小 Long size = ops.size("set-key"); System.out.println("size=" + size);
运行示例,输出结果:
values=[value2, value1, value4, value3] size=4
使用 scan() 方法可以对键的集合进行迭代,方法定义如下:
Cursor<V> scan(K key, ScanOptions options) 迭代 key 集合
ScanOptions 是用于 SCAN 命令的选项,ScanOptions 需要设置 pattern 和 count。其中:
pattern 指定匹配的模式
count 指定从数据集里返回多少元素,默认值为 10
示例:
Set<String> values; Cursor<String> cursor; SetOperations<String,String> ops = redisTemplate.opsForSet(); // 准备数据 for(int i = 0; i < 5; i++) { ops.add("set-key", "hello" + i, "world" + i, "value" + i); } // 迭代集合 // 构建一个默认的 ScanOptions 对象,不指定 count 和 pattern // 将迭代整个集合所有数据 values = new HashSet<>(); cursor = ops.scan("set-key", ScanOptions.scanOptions().build()); while (cursor.hasNext()) { values.add(cursor.next()); } System.out.println("values=" + Arrays.toString(values.toArray())); // 迭代所有 value 开头的元素 values = new HashSet<>(); cursor = ops.scan("set-key", ScanOptions.scanOptions() // 匹配所有 value 开头的元素 .match("value*").build()); while (cursor.hasNext()) { values.add(cursor.next()); } System.out.println("values=" + Arrays.toString(values.toArray())); // 迭代 2 个 value 开头的元素 values = new HashSet<>(); cursor = ops.scan("set-key", ScanOptions.scanOptions() .count(2L) // 匹配所有 value 开头的元素 .match("value*").build()); while (cursor.hasNext()) { values.add(cursor.next()); } System.out.println("values=" + Arrays.toString(values.toArray()));
运行示例,输出结果:
values=[world4, world2, world3, value2, hello0, value1, hello1, value4, value3, hello4, value0, hello2, hello3, world0, world1] values=[value2, value1, value4, value3, value0] values=[value2, value1, value4, value3, value0]