Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
6.1 应用场景
1.利用唯一性,可以存取当天的活跃用户列表、可以统计访问网站的所有独立 IP。
2.利用集合操作,以非常方便的实现如共同关注、共同喜好、二度好友等功能。对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存储到一个新的集合中。可以取不同兴趣圈子的交集,可以取当天的新增用户等。
6.2 代码示例
代码:com.javablog.redis.demo.service.impl.SetCacheServiceImpl
package com.javablog.redis.demo.service.impl;
import com.javablog.redis.demo.service.SetCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Set;
@Service("setCacheService")
public class SetCacheServiceImpl implements SetCacheService {
private final static Logger log = LoggerFactory.getLogger(SetCacheServiceImpl.class);
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 向变量中批量添加值。
* @param key 键
* @param objects 值
* @return true成功 false失败
*/
public boolean add(String key, Object...objects){
try {
redisTemplate.opsForSet().add(key,objects);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向变量中批量添加值。
* @param key 键
* @param expireTime 值
* @param values 值
* @return true成功 false失败
*/
@Override
public Boolean add(String key, int expireTime, Object... values) {
try {
redisTemplate.opsForSet().add(key,values);
if (expireTime > 0)
expire(key, expireTime);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* members(K key)获取变量中的值。
* @param key 键
* @return 返回Set对象
*/
public Set<Object> members(String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 获取变量中值的长度。
* @param key 键
* @return 返回SET的长度
*/
@Override
public long size(String key) {
return redisTemplate.opsForSet().size(key);
}
/**
* 检查给定的元素是否在变量中。
* @param key 键
* @param o 要检查的变量
* @return true存在 false不存在
*/
@Override
public boolean isMember(String key, Object o) {
return redisTemplate.opsForSet().isMember(key,o);
}
/**
* 转移变量的元素值到目的变量。
* @param key 键
* @param value 要转移的元素
* @param destValue 目标键
* @return true 成功 false 失败
*/
@Override
public boolean move(String key, Object value, String destValue) {
return redisTemplate.opsForSet().move(key,value,destValue);
}
/**
* 弹出变量中的元素。
* @param key 键
* @return 返回弹出的元素
*/
@Override
public Object pop(String key) {
return redisTemplate.opsForSet().pop(key);
}
/**
* 批量移除变量中的元素。
* @param key 键
* @param values 要移除的元素
* @return 返回移除元素个数
*/
@Override
public long remove(String key, Object... values) {
return redisTemplate.opsForSet().remove(key,values);
}
/**
* 匹配获取键值对
* @param key 键
* @param options 选项
* @return 返回键值对
*/
@Override
public Cursor<Object> scan(String key, ScanOptions options) {
return redisTemplate.opsForSet().scan(key,options);
}
/**
* 通过集合求差值。
* @param key 键
* @param list LIST中的对象是要比较缓存的KEY
* @return 返回差差值
*/
@Override
public Set<Object> difference(String key, List list) {
return redisTemplate.opsForSet().difference(key,list);
}
@Override
public Set<Object> difference(String key, String otherKeys) {
return redisTemplate.opsForSet().difference(key,otherKeys);
}
/**
* 将求出来的差值元素保存。
* @param key 键
* @param otherKey 要比较的缓存键
* @param destKey 要保存差值的缓存键
*/
@Override
public void differenceAndStore(String key, String otherKey, String destKey) {
redisTemplate.opsForSet().differenceAndStore(key,otherKey,destKey);
}
/**
* 将求出来的差值元素保存。
* @param key 键
* @param otherKeys 要比较的多个缓存键
* @param destKey 要保存差值的缓存键
*/
@Override
public void differenceAndStore(String key, List otherKeys, String destKey) {
redisTemplate.opsForSet().differenceAndStore(key,otherKeys,destKey);
}
/**
* 获取去重的随机元素。
* @param key 键
* @param count 数量
* @return 返回随机元素
*/
@Override
public Set<Object> distinctRandomMembers(String key, long count) {
return redisTemplate.opsForSet().distinctRandomMembers(key,count);
}
/**
* 获取2个变量中的交集。
* @param key 键
* @param otherKey 比较的缓存键
* @return 返回交集
*/
@Override
public Set<Object> intersect(String key, String otherKey) {
return redisTemplate.opsForSet().intersect(key,otherKey);
}
@Override
public Set<Object> intersect(String key, List list) {
return redisTemplate.opsForSet().intersect(key,list);
}
/**
* 获取2个变量交集后保存到最后一个参数上
* @param key 键
* @param otherKey 其它的缓存键
* @param destKey 交集键
*/
@Override
public void intersectAndStore(String key, String otherKey, String destKey) {
redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey);
}
/**
* 获取2个变量交集后保存到最后一个参数上
* @param key 键
* @param otherKey 其它的缓存键列表
* @param destKey 交集键
*/
@Override
public void intersectAndStore(String key, List otherKey, String destKey) {
redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey);
}
/**
* 获取2个变量的合集。
* @param key 键
* @param otherKey 要合的键
* @return 返回合并后的SET
*/
@Override
public Set<Object> union(String key, String otherKey) {
return redisTemplate.opsForSet().union(key,otherKey);
}
@Override
public Set<Object> union(String key, Set set) {
return redisTemplate.opsForSet().union(key,set);
}
/**
* 获取2个变量合集后保存到最后一个参数上。
* @param key 键
* @param otherKey 要合的键
* @param destKey 合并后的键
*/
@Override
public void unionAndStore(String key, String otherKey, String destKey) {
redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
}
/**获取2个变量合集后保存到最后一个参数上。
*
* @param key 键
* @param list 要合的键列表
* @param destKey 合并后的键
*/
@Override
public void unionAndStore(String key, List list, String destKey) {
redisTemplate.opsForSet().unionAndStore(key, list, destKey);
}
/**
* 随机获取变量中的元素。
* @param key 键
* @return 返回其中一个随机元素
*/
@Override
public Object randomMember(String key){
return redisTemplate.opsForSet().randomMember(key);
}
/**
* 随机获取变量中指定个数的元素
* @param key 键
* @param count 取随机数的个数
* @return 返回随机数LIST
*/
@Override
public List<Object> randomMembers(String key, long count){
return redisTemplate.opsForSet().randomMembers(key,count);
}
@Override
public void del(String... keys) {
if (keys != null && keys.length > 0) {
if (keys.length == 1) {
redisTemplate.delete(keys[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(keys));
}
}
}
}
6.3 测试用例(
代码:com.javablog.redis.demo.SetCacheServiceImplTest
package com.javablog.redis.demo;
import com.javablog.redis.demo.service.SetCacheService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = CacheServiceApplication.class)
@WebAppConfiguration
public class SetCacheServiceImplTest {
private final static Logger log = LoggerFactory.getLogger(SetCacheServiceImplTest.class);
@Autowired
private SetCacheService redisService;
@Test
public void testCacheSet(){
//add 观察有重复的数会去重
String key = "setkey";
redisService.add(key,"A","B","C","B","D","E","F");
//members(K key)获取变量中的值。
Set set = redisService.members(key);
System.out.println("通过members(K key)方法获取变量中的元素值:" + set);
//获取变量中值的长度。
long setLength = redisService.size(key);
System.out.println("通过size(K key)方法获取变量中元素值的长度:" + setLength);
// 随机获取变量中的元素。
Object randomMember = redisService.randomMember(key);
System.out.println("通过randomMember(K key)方法随机获取变量中的元素:" + randomMember);
// 随机获取变量中指定个数的元素。
List randomMembers = redisService.randomMembers(key,3);
System.out.println("通过randomMembers(K key, long count)方法随机获取变量中指定个数的元素:" + randomMembers);
// 检查给定的元素是否在变量中。
boolean isMember = redisService.isMember(key,"A");
System.out.println("通过isMember(K key, Object o)方法检查给定的元素是否在变量中:" + isMember);
//转移变量的元素值到目的变量。
boolean isMove = redisService.move(key,"A","destSetValue");
if(isMove){
set = redisService.members(key);
System.out.print("通过move(K key, V value, K destKey)方法转移变量的元素值到目的变量后的剩余元素:" + set);
set = redisService.members("destSetValue");
System.out.println(",目的变量中的元素值:" + set);
}
//弹出变量中的元素。
Object popValue = redisService.pop(key);
System.out.print("通过pop(K key)方法弹出变量中的元素:" + popValue);
set = redisService.members(key);
System.out.println(",剩余元素:" + set);
// 批量移除变量中的元素。
long removeCount = redisService.remove(key,"E","F","G");
System.out.print("通过remove(K key, Object... values)方法移除变量中的元素个数:" + removeCount);
set = redisService.members(key);
System.out.println(",剩余元素:" + set);
//匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。?
Cursor<Object> cursor = redisService.scan(key, ScanOptions.NONE);
// Cursor<Object> cursor = redisService.scan(key, ScanOptions.scanOptions().match("C").build());
while (cursor.hasNext()){
Object object = cursor.next();
System.out.println("通过scan(K key, ScanOptions options)方法获取匹配的值:" + object);
}
//通过集合求差值。
List<Object> list = new ArrayList();
list.add("destSetValue");
// redisService.add("destSetValue","B");
Set set1 = redisService.members("destSetValue");
System.out.println("通过members(K key)方法获取变量destSetValue中的元素值:" + set1);
Set differenceSet = redisService.difference(key,list);
System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定集合中变量不一样的值:" + differenceSet);
// 通过给定的key求2个set变量的差值。
differenceSet = redisService.difference(key,"destSetValue");
System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定变量不一样的值:" + differenceSet);
//将求出来的差值元素保存。
redisService.differenceAndStore(key,"destSetValue","storeSetValue");
set = redisService.members("storeSetValue");
System.out.println("通过differenceAndStore(K key, K otherKey, K destKey)方法将求出来的差值元素保存:" + set);
//将求出来的差值元素保存。
redisService.differenceAndStore(key,list,"storeSetValue");
set = redisService.members("storeSetValue");
System.out.println("通过differenceAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的差值元素保存:" + set);
//获取去重的随机元素。
set = redisService.distinctRandomMembers(key,2);
System.out.println("通过distinctRandomMembers(K key, long count)方法获取去重的随机元素:" + set);
//获取2个变量中的交集。
set = redisService.intersect(key,"destSetValue");
System.out.println("通过intersect(K key, K otherKey)方法获取交集元素:" + set);
// 获取多个变量之间的交集。
set = redisService.intersect(key,list);
System.out.println("通过intersect(K key, Collection<K> otherKeys)方法获取交集元素:" + set);
//获取2个变量交集后保存到最后一个参数上。
redisService.intersectAndStore(key,"destSetValue","intersectValue");
set = redisService.members("intersectValue");
System.out.println("通过intersectAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);
//获取多个变量的交集并保存到最后一个参数上。
redisService.intersectAndStore(key,list,"intersectListValue");
set = redisService.members("intersectListValue");
System.out.println("通过intersectAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set);
//获取2个变量的合集。
set = redisService.union(key,"destSetValue");
System.out.println("通过union(K key, K otherKey)方法获取2个变量的合集元素:" + set);
// 获取多个变量的合集。
set = redisService.union(key,list);
System.out.println("通过union(K key, Collection<K> otherKeys)方法获取多个变量的合集元素:" + set);
//获取2个变量合集后保存到最后一个参数上。
redisService.unionAndStore(key,"destSetValue","unionValue");
set = redisService.members("unionValue");
System.out.println("通过unionAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);
//获取多个变量的合集并保存到最后一个参数上。
redisService.unionAndStore(key,list,"unionListValue");
set = redisService.members("unionListValue");
System.out.println("通过unionAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set);
//删除
redisService.del(key);
set = redisService.members(key);
System.out.println("通过del(String... keys) 方法后查询结果:" + set);
}
}