Redis的常见数据结构
最近开始做项目了,利用redis进行连接操作。这里给出具体的数据结构分类,对于常见的大类型进行阐述,同时给出java中的方法调用~
1. Redis通用命令
通用指令是部分数据类型的,都可以使用的指令,常见的有:
- KEYS:查看符合模板的所有key
- DEL:删除一个指定的key
- EXISTS:判断key是否存在
- EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
- TTL:查看一个KEY的剩余有效期
通过help [command] 可以查看一个命令的具体用法,例如:
2. Redis数据结构
2.1 Redis命令-String命令
1. 基础知识和操作
-
String类型,也就是字符串类型,是Redis中最简单的存储类型。
-
其value是字符串,不过根据字符串的格式不同,又可以分为3类:
- string:普通字符串
- int:整数类型,可以做自增.自减操作
- float:浮点类型,可以做自增.自减操作
-
String的常见命令有:
- SET:添加或者修改已经存在的一个String类型的键值对 (
set name xkj) - GET:根据key获取String类型的value (
get name) - MSET:批量添加多个String类型的键值对 (
MSET k1 v1 k2 v2 k3 v3) - MGET:根据多个key获取多个String类型的value (
MGET name age k1 k2 k3) - INCR:让一个整型的key自增1 (
incr age) - INCRBY:让一个整型的key自增并指定步长,例如:
incrby num 2让num值自增2 - INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
- SETNX:添加一个String类型的键值对,前提是这个key不存在,否则不执行 (
setnx name lisi//如果key不存在,则添加成功
(integer) 0) - SETEX:添加一个String类型的键值对,并且指定有效期 (
setex name 10 jack) - SET 和GET: 如果key不存在则是新增,如果存在则是修改
- SET:添加或者修改已经存在的一个String类型的键值对 (
2. Java中操作字符串
@Component
public class RedisString {
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 新增一个字符串类型的值,key是键,value是值。
*
* set(K key, V value)
*/
public void set() {
// 存入永久数据
stringRedisTemplate.opsForValue().set("test2", "1");
// 也可以向redis里存入数据和设置缓存时间
stringRedisTemplate.opsForValue().set("test1", "hello redis", 1000, TimeUnit.SECONDS);
}
/**
* 批量插入,key值存在会覆盖原值
*
* multiSet(Map<? extends K,? extends V> map)
*/
public void multiSet() {
Map<String,String> map = new HashMap<>(16);
map.put("testMultiSet1", "value0");
map.put("testMultiSet2", "value2");
stringRedisTemplate.opsForValue().multiSet(map);
}
/**
* 批量插入,如果里面的所有key都不存在,则全部插入,返回true,如果其中一个在redis中已存在,全不插入,返回false
*
* multiSetIfAbsent(Map<? extends K,? extends V> map)
*/
public void multiSetIfAbsent() {
Map<String,String> map = new HashMap<>(16);
map.put("testMultiSet4", "value1");
map.put("testMultiSet3", "value3");
Boolean absent = stringRedisTemplate.opsForValue().multiSetIfAbsent(map);
System.out.println(absent);
}
/**
* 如果不存在则插入,返回true为插入成功,false失败
*
* setIfAbsent(K key, V value)
*/
public void setIfAbsent() {
Boolean absent = stringRedisTemplate.opsForValue().setIfAbsent("test", "hello redis");
System.out.println(absent);
}
/**
* 获取值,key不存在返回null
*
* get(Object key)
*/
public void get() {
System.out.println(stringRedisTemplate.opsForValue().get("testMultiSet1"));
}
/**
* 批量获取,key不存在返回null
*
* multiGet(Collection<K> keys)
*/
public void multiGet() {
List<String> list = stringRedisTemplate.opsForValue().multiGet(Arrays.asList("test", "test2"));
assert list != null;
System.out.println(list.toString());
}
/**
* 获取指定字符串的长度。
*
* size(K key)
*/
public void getLength() {
Long size = stringRedisTemplate.opsForValue().size("test");
System.out.println(size);
}
/**
* 在原有的值基础上新增字符串到末尾。
*
* append(K key, String value)
*/
public void append() {
Integer append = stringRedisTemplate.opsForValue().append("test3", "database");
System.out.println(append);
}
/**
* 获取原来key键对应的值并重新赋新值
*
* getAndSet(K key, V value)
*/
public void getAndSet() {
String set = stringRedisTemplate.opsForValue().getAndSet("test", "set test");
System.out.println(set);
}
/**
* 获取指定key的值进行减1,如果value不是integer类型,会抛异常,如果key不存在会创建一个,默认value为0
*
* decrement(k key)
*/
public void decrement() {
stringRedisTemplate.opsForValue().decrement("test2");
stringRedisTemplate.opsForValue().decrement("test1");
}
/**
* 获取指定key的值进行加1,如果value不是integer类型,会抛异常,如果key不存在会创建一个,默认value为0
*
* increment(k key)
*/
public void increment() {
stringRedisTemplate.opsForValue().increment("test2");
stringRedisTemplate.opsForValue().increment("test1");
}
/**
* 删除指定key,成功返回true,否则false
*
* delete(k key)
*/
public void delete() {
Boolean delete = stringRedisTemplate.opsForValue().getOperations().delete("test1");
System.out.println(delete);
}
/**
* 删除多个key,返回删除key的个数
*
* delete(k ...keys)
*/
public void deleteMulti() {
Long delete = stringRedisTemplate.opsForValue().getOperations().delete(Arrays.asList("test1", "test2"));
System.out.println(delete);
}
}
3. 使用场景
-
缓存:将数据以字符串方式存储
-
计数器功能:比如视频播放次数,点赞次数。
-
共享session:数据共享的功能,redis作为单独的应用软件用来存储一些共享数据供多个实例访问。
字符串的使用空间非常大,可以结合字符串提供的命令充分发挥自己的想象力
4. (附) Redis命令-Key的层级结构
-
我们可以通过给key添加前缀加以区分,不过这个前缀不是随便加的,有一定的规范:
-
Redis的key允许有多个单词形成层级结构,多个单词之间用’:'隔开,格式如下:
项目名:业务名:类型:id
-
如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:
| KEY | VALUE
| xkj:user:1 | {“id”:1, “name”: “Jack”, “age”: 21} |
| xkj:product:1 | {“id”:1, “name”: “华为Mate 60 pro”, “price”: 6999} |
2.2 Redis命令-Hash命令
1. 基础知识和操作
-
Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。
-
String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便,如上表格所示:
-
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:
-
Hash类型的常见命令
-
HSET key field value:添加或者修改hash类型key的field的值
HSET user:3 name Lucy -
HGET key field:获取一个hash类型key的field的值
HGET :user:3 name -
HMSET:批量添加多个hash类型key的field的值
HMSET user:4 name LiLei age 20 sex man -
HMGET:批量获取多个hash类型key的field的值
HMGET user:4 name age sex- “LiLei”
- “20”
- “man”
-
HGETALL:获取一个hash类型的key中的所有的field和value
HGETALL user:4 -
HKEYS:获取一个hash类型的key中的所有的field
HKEYS user:4 -
HVALS:获取所有的键对应的值
HVALS user:4 -
HINCRBY:让一个hash类型key的字段值自增并指定步长
HINCRBY user:4 age 2 -
HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行;同时也存在HGETALL,得到全体的
fields和value匹配HSETNX user:4 sex womanHGETALL user:4- “name”
- “Lucy”
- “age”
- “17”
- “sex”
- “woman”
-
2. Java中操作HashMap
@Component
public class RedisHash {
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 新增hashMap值
*
* put(H key, HK hashKey, HV value)
*/
public void put() {
stringRedisTemplate.opsForHash().put("hash","hash-key","hash-value");
stringRedisTemplate.opsForHash().put("hash","hash-key2","hash-value2");
}
/**
* 以map集合的形式添加键值对
*
* putAll(H key, Map<? extends HK,? extends HV> m)
*/
public void putAll() {
Map<String, String> map = new HashMap<>(16);
map.put("hash-key3", "value3");
map.put("hash-key4", "value4");
stringRedisTemplate.opsForHash().putAll("hash", map);
}
/**
* 如果变量值存在,在变量中可以添加不存在的的键值对,如果变量不存在,则新增一个变量,同时将键值对添加到该变量。添加成功返回true否则返回false
*
* putIfAbsent(H key, HK hashKey, HV value)
*/
public void putIfAbsent() {
Boolean absent = stringRedisTemplate.opsForHash().putIfAbsent("hash", "hash-key", "value1");
Boolean absent2 = stringRedisTemplate.opsForHash().putIfAbsent("hash", "hash-key5", "value5");
System.out.println(absent);
System.out.println(absent2);
}
/**
* 获取指定变量中的hashMap值。
*
* values(H Key)
*/
public void values() {
List<Object> values = stringRedisTemplate.opsForHash().values("hash2");
System.out.println(values.toString());
}
/**
* 获取变量中的键值对。
*
* entries(H key)
*/
public void entries() {
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("hash");
System.out.println(entries.toString());
}
/**
* 获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null。
*
* get(H key, Object hashKey)
*/
public void get() {
Object value = stringRedisTemplate.opsForHash().get("hash", "hash-key");
System.out.println(value);
}
/**
* 获取变量中的键。
*
* keys(H key)
*/
public void keys() {
Set<Object> keys = stringRedisTemplate.opsForHash().keys("hash");
System.out.println(keys.toString());
}
/**
* 获取变量的长度
*
* size(H key)
*/
public void size() {
Long size = stringRedisTemplate.opsForHash().size("hash");
System.out.println(size);
}
/**
* 使变量中的键以long值的大小进行自增长。值必须为Integer类型,否则异常
*
* increment(H key, HK hashKey, long data)
*/
public void increment() {
Long increment = stringRedisTemplate.opsForHash().increment("hash", "hash-key2", 1);
System.out.println(increment);
}
/**
* 以集合的方式获取变量中的值。
*
* multiGet(H key, Collection<HK> hashKeys)
*/
public void multiGet() {
List<Object> values = stringRedisTemplate.opsForHash().multiGet("hash", Arrays.asList("hash-key", "hash-key2"));
System.out.println(values.toString());
}
/**
* 匹配获取键值对,ScanOptions.NONE为获取全部键对,ScanOptions.scanOptions().match("hash-key2").build()匹配获取键位map1的键值对,不能模糊匹配。
*
* scan(H key, ScanOptions options)
*/
public void scan() {
Cursor<Map.Entry<Object, Object>> scan = stringRedisTemplate.opsForHash().scan("hash", ScanOptions.NONE);
while (scan.hasNext()) {
Map.Entry<Object, Object> next = scan.next();
System.out.println(next.getKey() + "---->" + next.getValue());
}
}
/**
* 删除变量中的键值对,可以传入多个参数,删除多个键值对。返回删除成功数量
*
* delete(H key, Object... hashKeys)
*/
public void delete() {
Long delete = stringRedisTemplate.opsForHash().delete("hash", "hash-key", "hash-key1");
System.out.println(delete);
}
}
3. 使用场景
-
字典。键值对集合,即编程语言中的Map类型。
-
适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值。
-
适用于:存储、读取、修改用户属性。也可以用Hash做表数据缓存
2.3 Redis命令-List命令
1. 基础知识和操作
-
Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。
-
特征也与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
-
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
-
List常见命令有:
-
LPUSH key element … :向列表左侧插入一个或多个元素
LPUSH users 1 2 3 -
LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
LPOP users "3" -
RPUSH key element … :向列表右侧插入一个或多个元素
-
RPOP key:移除并返回列表右侧的第一个元素
-
LRANGE key star end:返回一段角标范围内的所有元素
LRANGE users 1 2 -
BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil。
-
如何利用List结构模拟一个栈?
•入口和出口在同一边(LPUSH LPOP)
如何利用List结构模拟一个队列?
•入口和出口在不同边 (LPUSH RPOP)
如何利用List结构模拟一个阻塞队列?
•入口和出口在不同边
•出队时采用BLPOP或BRPOP
2. Java中操作集合
@Component
public class RedisList {
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 在变量左边添加元素值。如果key不存在会新建,添加成功返回添加后的总个数
*
* leftPush(K key, V value)
*/
public void leftPush() {
Long aLong = stringRedisTemplate.opsForList().leftPush("list", "a");
System.out.println(aLong);
}
/**
* 向左边批量添加参数元素,如果key不存在会新建,添加成功返回添加后的总个数
*
* leftPushAll(K key, V... values)
*/
public void leftPushAll() {
Long pushAll = stringRedisTemplate.opsForList().leftPushAll("list", "e", "f", "g");
System.out.println(pushAll);
}
/**
* 向集合最右边添加元素。如果key不存在会新建,添加成功返回添加后的总个数
*
* rightPush(K key, V value)
*/
public void rightPush() {
Long aLong = stringRedisTemplate.opsForList().rightPush("list2", "a");
System.out.println(aLong);
}
/**
* 如果存在集合则添加元素。
*
* leftPushIfPresent(K key, V value)
*/
public void leftPushIfPresent() {
Long aLong = stringRedisTemplate.opsForList().leftPushIfPresent("list", "h");
System.out.println(aLong);
}
/**
* 向右边批量添加元素。返回当前集合元素总个数
*
* rightPushAll(K key, V... values)
*/
public void rightPushAll() {
Long aLong = stringRedisTemplate.opsForList().rightPushAll("list2", "b", "c", "d");
System.out.println(aLong);
}
/**
* 向已存在的集合中添加元素。返回集合总元素个数
*
* rightPushIfPresent(K key, V value)
*/
public void rightPushIfPresent() {
Long aLong = stringRedisTemplate.opsForList().rightPushIfPresent("list", "e");
System.out.println(aLong);
}
/**
* 获取集合长度
*
* size(K key)
*/
public void size() {
Long size = stringRedisTemplate.opsForList().size("list2");
System.out.println(size);
}
/**
* 移除集合中的左边第一个元素。返回删除的元素,如果元素为空,该集合会自动删除
*
* leftPop(K key)
*/
public void leftPop() {
String pop = stringRedisTemplate.opsForList().leftPop("list2");
System.out.println(pop);
}
/**
* 移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
*
* leftPop(K key, long timeout, TimeUnit unit)
*/
public void leftPopWait() {
String pop = stringRedisTemplate.opsForList().leftPop("list2", 10, TimeUnit.SECONDS);
System.out.println(pop);
}
/**
* 移除集合中右边的元素。返回删除的元素,如果元素为空,该集合会自动删除
*
* rightPop(K key)
*/
public void rightPop() {
String pop = stringRedisTemplate.opsForList().rightPop("list2");
System.out.println(pop);
}
/**
* 移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
*
* rightPop(K key, long timeout, TimeUnit unit)
*/
public void rightPopWait() {
String pop = stringRedisTemplate.opsForList().rightPop("list2", 10, TimeUnit.SECONDS);
System.out.println(pop);
}
/**
* 移除第一个集合右边的一个元素,插入第二个集合左边插入这个元素
*
* rightPopAndLeftPush(K sourceKey, K destinationKey)
*/
public void rightPopAndLeftPush() {
String s = stringRedisTemplate.opsForList().rightPopAndLeftPush("list2", "list3");
System.out.println(s);
}
/**
* 在集合的指定位置插入元素,如果指定位置已有元素,则覆盖,没有则新增,超过集合下标+n则会报错。
*
* set(K key, long index, V value)
*/
public void set() {
stringRedisTemplate.opsForList().set("list2", 2, "w");
}
/**
* 从存储在键中的列表中删除等于值的元素的第一个计数事件。count> 0:删除等于从左到右移动的值的第一个元素;
* count< 0:删除等于从右到左移动的值的第一个元素;count = 0:删除等于value的所有元素
*
* remove(K key, long count, Object value)
*/
public void remove() {
Long remove = stringRedisTemplate.opsForList().remove("list2", 2, "w");
System.out.println(remove);
}
/**
* 截取集合元素长度,保留长度内的数据。
*
* trim(K key, long start, long end)
*/
public void trim() {
stringRedisTemplate.opsForList().trim("list2", 0, 3);
}
/**
* 获取集合指定位置的值。
*
* index(K key, long index)
*/
public void index() {
Object listValue = stringRedisTemplate.opsForList().index("list2", 3);
System.out.println(listValue);
}
/**
* 获取指定区间的值。
*
* range(K key, long start, long end)
*/
public void range() {
List<String> list = stringRedisTemplate.opsForList().range("list", 0, -1);
System.out.println(list);
}
/**
* 删除指定集合,返回true删除成功
*
* delete(K key)
*/
public void delete() {
Boolean delete = stringRedisTemplate.opsForList().getOperations().delete("list2");
System.out.println(delete);
}
}
3. 使用场景
-
链表(双向链表),增删快,提供了操作某一段元素的API。适用于:最新消息排行等功能;消息队列。
2.4 Redis命令-Set命令
1. 基础知识和操作
-
Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:
- 无序
- 元素不可重复
- 查找快
- 支持交集.并集.差集等功能
-
Set类型的常见命令
-
SADD key member … :向set中添加一个或多个元素
sadd s1 a b c -
SREM key member … : 移除set中的指定元素
srem s1 a -
SCARD key: 返回set中元素的个数
SCARD s1 -
SISMEMBER key member:判断一个元素是否存在于set中
SISMEMBER s1 a -
SMEMBERS:获取set中的所有元素(无序返回)
smembers s1- “c”
- “b”
- “a”
-
SINTER key1 key2 … :求key1与key2的交集
-
SDIFF key1 key2 … :求key1与key2的差集
-
SUNION key1 key2 …:求key1和key2的并集
-
2. Java中操作set集合
/**
* 以下可能有部分方法含有参数传Collection的,本案例没有描述,你们可以根据实际参数类型传参
**/
@Component
public class RedisSet {
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 向变量中批量添加值。返回添加的数量
*
* add(K key, V... values)
*/
public void add() {
Long add = stringRedisTemplate.opsForSet().add("set", "a", "b", "c");
System.out.println(add);
}
/**
* 获取变量的值
*
* members(K key)
*/
public void members() {
Set<String> set = stringRedisTemplate.opsForSet().members("set");
System.out.println(set);
}
/**
* 获取变量中值得长度
*
* size(k key)
*/
public void size() {
Long size = stringRedisTemplate.opsForSet().size("set");
System.out.println(size);
}
/**
* 随机获取变量中的某个元素
*
* randomMember(k key)
*/
public void randomMember() {
String member = stringRedisTemplate.opsForSet().randomMember("set");
System.out.println(member);
}
/**
* 随机获取变量中指定个数的元素
*
* randomMembers(k key, long count)
*/
public void randomMembers() {
List<String> members = stringRedisTemplate.opsForSet().randomMembers("set", 2);
System.out.println(members);
}
/**
* 检查给定的元素是否在变量中,true为存在
*
* isMember(k key, object value)
*/
public void isMember() {
Boolean member = stringRedisTemplate.opsForSet().isMember("set", "b");
System.out.println(member);
}
/**
* 转义变量的元素值到另一个变量中
*
* move(k key, v value, k targetKey)
*/
public void move() {
Boolean move = stringRedisTemplate.opsForSet().move("set", "b", "set2");
System.out.println(move);
}
/**
* 弹出变量中的元素。当元素全部弹完,变量也会删除
*
* pop(k key)
*/
public void pop() {
String pop = stringRedisTemplate.opsForSet().pop("set");
System.out.println(pop);
}
/**
* 批量删除变量中的元素,返回删除的数量
*
* remove(k key, v ...values)
*/
public void remove() {
Long remove = stringRedisTemplate.opsForSet().remove("set2", "b");
System.out.println(remove);
}
/**
* 匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
*
* scan(K key, ScanOptions options)
*/
public void scan() {
Cursor<String> set = stringRedisTemplate.opsForSet().scan("set", ScanOptions.NONE);
while (set.hasNext()) {
String next = set.next();
System.out.println(next);
}
}
/**
* 通过集合求差值。
*
* difference(k key, k otherKey)
*/
public void difference() {
Set<String> difference = stringRedisTemplate.opsForSet().difference("set", "set2");
System.out.println(difference);
}
/**
* 将求出来的差值元素保存
*
* differenceAndStore(K key, K otherKey, K targetKey)
*/
public void differenceAndStore() {
Long aLong = stringRedisTemplate.opsForSet().differenceAndStore("set", "set2", "set3");
System.out.println(aLong);
}
/**
* 获取去重的随机元素
*
* distinctRandomMembers(K key, long count)
*/
public void distinctRandomMembers() {
Set<String> set = stringRedisTemplate.opsForSet().distinctRandomMembers("set", 2);
System.out.println(set);
}
/**
* 获取两个变量中的交集
*
* intersect(K key, K otherKey)
*/
public void intersect() {
Set<String> intersect = stringRedisTemplate.opsForSet().intersect("set", "set2");
System.out.println(intersect);
}
/**
* 获取2个变量交集后保存到最后一个变量上。
*
* intersectAndStore(K key, K otherKey, K targetKey)
*/
public void intersectAndStore() {
Long aLong = stringRedisTemplate.opsForSet().intersectAndStore("set", "set2", "set3");
System.out.println(aLong);
}
/**
* 获取两个变量的合集
*
* union(K key, K otherKey)
*/
public void union() {
Set<String> union = stringRedisTemplate.opsForSet().union("set", "set2");
System.out.println(union);
}
/**
* 获取两个变量合集后保存到另一个变量中
*
* unionAndStore(K key, K otherKey, K targetKey)
*/
public void unionAndStore() {
Long aLong = stringRedisTemplate.opsForSet().unionAndStore("set", "set2", "set3");
System.out.println(aLong);
}
}
3. 使用场景
-
集合。哈希表实现,元素不重复,为集合提供了求交集、并集、差集等操作。
-
适用于:共同好友;利用唯一性,统计访问网站的所有独立ip;
好友推荐时,根据tag求交集,大于某个阈值就可以推荐。
2.5 Redis命令-SortedSet类型
1. 基础知识和操作
-
Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。
-
SortedSet具备下列特性:
-
可排序
-
元素不重复
-
查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
-
-
SortedSet的常见命令:
-
用法和SET类似:
- ZADD key score member:添加一个或多个元素到sorted set ,如果已经存在则更新其score值
- ZREM key member:删除sorted set中的一个指定元素
- ZSCORE key member : 获取sorted set中的指定元素的score值
- ZRANK key member:获取sorted set 中的指定元素的排名
- ZCARD key:获取sorted set中的元素个数
- ZCOUNT key min max:统计score值在给定范围内的所有元素的个数
- ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的increment值
- ZRANGE key min max:按照score排序后,获取指定排名范围内的元素
- ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素
- ZDIFF.ZINTER.ZUNION:求差集.交集.并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可,例如:
- 升序获取sorted set 中的指定元素的排名:ZRANK key member
- 降序获取sorted set 中的指定元素的排名:ZREVRANK key memeber
2. Java中操作~ZSET
@Component
public class RedisZSet {
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 添加元素到变量中同时指定元素的分值。
*
* add(K key, V value, double score)
*/
public void add() {
Boolean add = stringRedisTemplate.opsForZSet().add("zset", "a", 1);
System.out.println(add);
}
/**
* 通过TypedTuple方式新增数据。
*
* add(K key, Set<ZSetOperations.TypedTuple<V>> tuples)
*/
public void addByTypedTuple() {
ZSetOperations.TypedTuple<String> typedTuple1 = new DefaultTypedTuple<>("E", 2.0);
ZSetOperations.TypedTuple<String> typedTuple2 = new DefaultTypedTuple<>("F", 3.0);
ZSetOperations.TypedTuple<String> typedTuple3 = new DefaultTypedTuple<>("G", 5.0);
Set<ZSetOperations.TypedTuple<String>> typedTupleSet = new HashSet<>();
typedTupleSet.add(typedTuple1);
typedTupleSet.add(typedTuple2);
typedTupleSet.add(typedTuple3);
Long zset = stringRedisTemplate.opsForZSet().add("zset", typedTupleSet);
System.out.println(zset);
}
/**
* 获取指定区间的元素
*
* range(k key, long start, long end)
*/
public void range() {
Set<String> zset = stringRedisTemplate.opsForZSet().range("zset", 0, -1);
System.out.println(zset);
}
/**
* 用于获取满足非score的排序取值。这个排序只有在有相同分数的情况下才能使用,如果有不同的分数则返回值不确定。
*
* rangeByLex(K key, RedisZSetCommands.Range range)
*/
public void rangeByLex() {
Set<String> rangeByLex = stringRedisTemplate.opsForZSet().rangeByLex("zset", RedisZSetCommands.Range.range().lt("E"));
System.out.println(rangeByLex);
}
/**
* 用于获取满足非score的设置下标开始的长度排序取值。
*
* rangeByLex(k key, range range, limit limit)
*/
public void rangeByLexAndLimit() {
Set<String> zset = stringRedisTemplate.opsForZSet().rangeByLex("zset", RedisZSetCommands.Range.range().lt("E"),
RedisZSetCommands.Limit.limit().offset(1).count(2));
System.out.println(zset);
}
/**
* 根据设置的score获取区间值。
*
* rangeByScore(K key, double min, double max)
*/
public void rangeByScore() {
Set<String> zset = stringRedisTemplate.opsForZSet().rangeByScore("zset", 1, 3);
System.out.println(zset);
}
/**
* 获取RedisZSetCommands.Tuples的区间值。
*
* rangeWithScores(K key, long start, long end)
*/
public void rangeWithScores() {
Set<ZSetOperations.TypedTuple<String>> zset = stringRedisTemplate.opsForZSet().rangeWithScores("zset", 1, 3);
assert zset != null;
for (ZSetOperations.TypedTuple<String> next : zset) {
String value = next.getValue();
Double score = next.getScore();
System.out.println(value + "-->" + score);
}
}
/**
* 获取区间值的个数。
*
* count(k key, double min, double max)
*/
public void count() {
Long zset = stringRedisTemplate.opsForZSet().count("zset", 1, 3);
System.out.println(zset);
}
/**
* 获取变量中指定元素的索引,下标开始为0
*
* rank(k key, object o)
*/
public void rank() {
Long rank = stringRedisTemplate.opsForZSet().rank("zset", "a");
System.out.println(rank);
}
/**
* 匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
*
* scan(K key, ScanOptions options)
*/
public void scan() {
Cursor<ZSetOperations.TypedTuple<String>> zset = stringRedisTemplate.opsForZSet().scan("zset", ScanOptions.NONE);
while (zset.hasNext()) {
ZSetOperations.TypedTuple<String> next = zset.next();
System.out.println(next.getValue() + "-->" + next.getScore());
}
}
/**
* 获取指定元素的分值
*
* score(k key, object o)
*/
public void score() {
Double score = stringRedisTemplate.opsForZSet().score("zset", "a");
System.out.println(score);
}
/**
* 获取变量中元素的个数
*
* zCard(k key)
*/
public void zCard() {
Long zset = stringRedisTemplate.opsForZSet().zCard("zset");
System.out.println(zset);
}
/**
* 修改变量中元素的分值
*
* incrementScore(K key, V value, double delta)
*/
public void incrementScore() {
Double score = stringRedisTemplate.opsForZSet().incrementScore("zset", "a", 2);
System.out.println(score);
}
/**
* 索引倒序排列指定区间的元素
*
* reverseRange(K key, long start, long end)
*/
public void reverseRange() {
Set<String> zset = stringRedisTemplate.opsForZSet().reverseRange("zset", 1, 3);
System.out.println(zset);
}
/**
* 倒序排列指定分值区间的元素
*
* reverseRangeByScore(K key, double min, double max)
*/
public void reverseRangeByScore() {
Set<String> zset = stringRedisTemplate.opsForZSet().reverseRangeByScore("zset", 1, 3);
System.out.println(zset);
}
/**
* 倒序排序获取RedisZSetCommands.Tuples的分值区间值
*
* reverseRangeByScore(K key, double min, double max, long offset, long count)
*/
public void reverseRangeByScoreLength() {
Set<String> zset = stringRedisTemplate.opsForZSet().reverseRangeByScore("zset", 1, 3, 1, 2);
System.out.println(zset);
}
/**
* 倒序排序获取RedisZSetCommands.Tuples的分值区间值。
*
* reverseRangeByScoreWithScores(K key, double min, double max)
*/
public void reverseRangeByScoreWithScores() {
Set<ZSetOperations.TypedTuple<String>> zset = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores("zset", 1, 5);
assert zset != null;
zset.iterator().forEachRemaining(e-> System.out.println(e.getValue() + "--->" + e.getScore()));
}
/**
* 获取倒序排列的索引值
*
* reverseRank(k key, object o)
*/
public void reverseRank() {
Long aLong = stringRedisTemplate.opsForZSet().reverseRank("zset", "a");
System.out.println(aLong);
}
/**
* 获取2个变量的交集存放到第3个变量里面。
*
* intersectAndStore(K key, K otherKey, K destKey)
*/
public void intersectAndStore() {
Long aLong = stringRedisTemplate.opsForZSet().intersectAndStore("zset", "zset2", "zset3");
System.out.println(aLong);
}
/**
* 获取2个变量的合集存放到第3个变量里面。 返回操作的数量
*
* unionAndStore(K key, K otherKey, K destKey)
*/
public void unionAndStore() {
Long aLong = stringRedisTemplate.opsForZSet().unionAndStore("zset", "zset2", "zset3");
System.out.println(aLong);
}
/**
* 批量移除元素根据元素值。返回删除的元素数量
*
* remove(K key, Object... values)
*/
public void remove() {
Long remove = stringRedisTemplate.opsForZSet().remove("zset", "a", "b");
System.out.println(remove);
}
/**
* 根据分值移除区间元素。返回删除的数量
*
* removeRangeByScore(k key, double min, double max)
*/
public void removeRangeByScore() {
Long zset = stringRedisTemplate.opsForZSet().removeRangeByScore("zset", 1, 3);
System.out.println(zset);
}
/**
* 根据索引值移除区间元素。返回移除的元素集合
*
* removeRange(K key, long start, long end)
*/
public void removeRange() {
Set<String> zset = stringRedisTemplate.opsForZSet().reverseRange("zset", 0, 4);
System.out.println(zset);
}
}
3. 使用场景
-
有序集合。将Set中的元素增加一个权重参数score,元素按score有序排列。
-
数据插入集合时,已经进行天然排序。适用于:排行榜;带权重的消息队列。
3. Java中的数据处理
StringRedisTemplate与RedisTemplate的区别?
- 两者的关系是StringRedisTemplate继承RedisTemplate。
- 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据
- RedisTemplate只能管RedisTemplate中的数据。
SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。- StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
- RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
今天将博客的代码块实现更新,现在有高亮的功能了,看起来还是很舒服的~