大家好,我是小趴菜,对于Redis相信大家并不陌生,但是对于Redis基础的几种数据结构的一些方法可能还了解不多,今天来帮大家总结一下Redis基础数据结构的基本API以及使用案例
String
Redis的字符串存储字节序列,包括文本、序列化的对象和二进制数组。因此,字符串是最简单的值类型,可以与Redis键相关联。它们通常用于缓存,但也支持额外的功能,使您可以实现计数器和执行位操作。
由于Redis键是字符串,当我们使用字符串类型作为值时,我们将字符串映射到另一个字符串。字符串数据类型适用于许多用例,例如缓存HTML片段或页面。
js
//最基本的GET,SET方法
String res1 = jedis.set("bike:1", "Deimos");
System.out.println(res1); // OK
String res2 = jedis.get("bike:1");
System.out.println(res2); // Deimos
//当这个值不存在的时候才能设置成功,设置成功返回1,不成功返回0
Long res3 = jedis.setnx("bike:1", "bike");
//当这个值存在的时候才能设置成功,不存在就失败
//设置成功返回OK,失败返回null
String res4 = jedis.set("bike:4", "bike-1-xpc", SetParams.setParams().xx());
//当我们要设置多个值的时候,我们可以使用for循环,然后执行SET操作,但是如果有n个键值对的话,那么
//就会产生n次的网络IO,我们可以使用mset命令来减少redis的网络IO操作,提高性能
String mset = jedis.mset("xpc:1", "xpc-1", "xpc:2", "xpc-2", "xpc:3", "xpc-3");
System.out.println(mset);
//批量获取
List<String> mget = jedis.mget("xpc:1", "xpc:2", "xpc:3");
mget.parallelStream().forEach(x -> System.out.println(x));
//INCR命令将字符串值解析为整数,并将其增加1,最后将获得的值设置为新值
//INCR命令具有原子行,即使多个客户端同时修改,也不会有竞争关系
jedis.set("count","0");
jedis.incr("count");
System.out.println(jedis.get("count")); // 1
jedis.incrBy("count",10);
System.out.println(jedis.get("count")); // 11
jedis.decr("count");
System.out.println(jedis.get("count")); // 10
jedis.decrBy("count",5);
System.out.println(jedis.get("count")); // 5
jedis.decrBy("count",10);
System.out.println(jedis.get("count")); // -5
- 注意:默认情况下,单个Redis字符串的最大容量为512MB。
String耗时操作
大多数字符串操作都是O(1),这意味着它们非常高效。但是,要小心SUBSTR、GETRANGE和SETRANGE命令,它们可能是O(n)。这些随机访问字符串命令在处理大型字符串时可能会导致性能问题。
js
jedis.set("xpc:5","xpc66666");
//SUBSTR操作:截取字符串,类似Java中的subString
System.out.println(jedis.substr("xpc:5", 0, 3)); // xpc6
//GETRANGE操作:截取字符串,类似Java中的subString
System.out.println(jedis.getrange("xpc:5", 1, 4)); // pc66
//如果你的索引没有超出字符串的长度,那就是字符替换,如果超出了就是字符拼接
jedis.setrange("xpc:5",0,"coco");
System.out.println(jedis.get("xpc:5")); // xpc66666 -> coco6666
jedis.setrange("xpc:5",8,"redis");
System.out.println(jedis.get("xpc:5")); // coco66666 -> coco6666redis
List
Redis列表是字符串值的链表。Redis列表常用于:实现堆栈和队列。 为后台工作系统构建队列管理。 List有一些基础的命令,包括LPUSH,RPUSH,LPOP,RPOP.......等,接下来一一为大家介绍
js
//LPUSH是从链表的头节点插入元素,如果这个链表不存在,就会自动创建
jedis.lpush("xpc:list","xpc-1","xpc-2"); // xpc-2 -> xpc-1
//LRPUSH是从链表的尾节点插入元素
jedis.rpush("xpc:list","xpc-3","xpc-4");// xpc-2 -> xpc-1 -> xpc-3 -> xpc-4
// RPOP是移除尾节点并返回这个元素,如果链表为空,就返回null
System.out.println(jedis.rpop("xpc:list"));
// LPOP是移除头节点并返回这个元素,如果链表为空,就返回null
System.out.println(jedis.lpop("xpc:list"));
// LLEN是返回链表的元素个数
System.out.println(jedis.llen("xpc:list"));
//LTRIM截取索引0,1二个元素,是左闭右闭,
//xpc-2 -> xpc-1 -> xpc-3 -> xpc-4
//一般来说是截取链表中的某几个连续的元素
String ltrim = jedis.ltrim("xpc:list", 0, 1); // 截取之后链表元素为:xpc-2 -> xpc-1
//RPOP.LPOP都是非阻塞的,也就是说如果链表有元素就返回。没有也是立即返回一个null
//BLPOP,BRPOP是阻塞的,也就是说如果链表有元素就返回。没有就会阻塞一段时间,默认单位是秒,如果
//超过5秒还是没有元素,那么就返回一个null
//从尾节点拿数据
List<String> brpop = jedis.brpop(5, "xpc:list");
//从头节点拿数据
List<String> brpop = jedis.blpop(5, "xpc:list");
//BLPOP,BRPOP还可以监听多个key
List<String> brpop = jedis.brpop(5, "xpc:list","xpc:list:1","xpc:list:1");
List<String> brpop = jedis.blpop(5, "xpc:list","xpc:list:1","xpc:list:1");
//LRANG就类似MySQl的limit分页,索引也是从0开始,是左闭右闭,
List<String> lrange = jedis.lrange("xpc:list", 0, 10);
- 注意:Redis列表的最大长度为2^32 - 1(4,294,967,295)个元素。
List耗时操作
访问头或尾的列表操作是O(1),这意味着它们效率很高。但是,操作列表中元素的命令通常是O (n)。其中的例子包括LINDEX、LINSERT和LSET。运行这些命令时要小心,尤其是在处理大型列表时。
js
//LINDEX返回指定索引的数据
System.out.println(jedis.lindex("xpc:list", 1));
//超出链表长度直接返回null
System.out.println(jedis.lindex("xpc:list", 10));
//在指定索引下插入元素
jedis.lset("xpc:list",1,"xpc-9");
Set
Redis的集合(set)是一个无序的字符串集合,其中的每个字符串都是唯一的。您可以使用Redis的集合来高效地执行以下操作:
追踪唯一的项(例如,追踪访问特定博客文章的所有唯一IP地址)。 表示关系(例如,具有特定角色的所有用户的集合)。 执行常见的集合操作,例如交集、并集和差集
Set有一些基础的命令,SADD,SREM,SISMEMBER,SINTER.......等,接下来一一为大家介绍
js
//SADD将新成员添加到集合中,如果这个元素不存在,就返回1,如果存在这个元素就返回0
Long sadd = jedis.sadd("xpc:1", "xpc-1");
System.out.println(sadd); // 1
Long sadd1 = jedis.sadd("xpc:1", "xpc-1");
System.out.println(sadd1); // 0
Long sadd2 = jedis.sadd("xpc:1", "xpc-2");
System.out.println(sadd2); // 1
//SREM删除指定元素
System.out.println(jedis.srem("xpc:1", "xpc-1")); // 1
//删除之后再添加
System.out.println(jedis.sadd("xpc:1", "xpc-1")); // 1
//如果删除一个不存在的元素,就返回0
System.out.println(jedis.srem("xpc:1", "xpc-1")); // 0
//SISMEMBER判断该元素是否存在与集合中,存在返回true,不存在返回false
System.out.println(jedis.sismember("xpc:1", "xpc-100")); // false
System.out.println(jedis.sismember("xpc:1", "xpc-1")); // true
//会返回"xpc:2", "xpc:1"二个集合都存在的元素,也就是二个集合的交集
Set<String> sinter = jedis.sinter("xpc:2", "xpc:1");
// scard返回集合的大小
System.out.println(jedis.scard("xpc:1"));
// sidff返回的二个集合的差集
//注意:这里返回的是xpc:1这个集合存在,但是xpc:2这个集合不存在的元素
//如果你要返回xpc:2这个集合存在,但是xpc:1这个集合不存在的元素,把二个集合顺序换一下即可
Set<String> sdiff = jedis.sdiff("xpc:1", "xpc:2");
//返回二个集合的并集,也就是返回二个集合的所有元素
Set<String> sunion = jedis.sunion("xpc:1", "xpc:2");
//从集合中随机移除3个元素
Set<String> spop = jedis.spop("xpc-3", 3);
//从集合中随机获取2个元素
List<String> srandmember = jedis.srandmember("xpc-3", 2);
Hashes
Redis的散列类型是有结构的数据类型,它们是字段-值对的集合。你可以使用散列来表达基本对象,以及存储计数器的分组等等。
js
Map<String, String> bike1 = new HashMap<>();
bike1.put("model", "Deimos");
bike1.put("brand", "Ergonom");
bike1.put("type", "Enduro bikes");
bike1.put("price", "4972");
//设置value
Long res1 = jedis.hset("bike:1", bike1);
System.out.println(res1); // 4
//获取model属性的值
String res2 = jedis.hget("bike:1", "model");
System.out.println(res2); // Deimos
//获取price属性的值
String res3 = jedis.hget("bike:1", "price");
System.out.println(res3); // 4972
//获取整个对象的值
Map<String, String> res4 = jedis.hgetAll("bike:1");
System.out.println(res4); // {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
//同时获取多个属性的值
List<String> res5 = jedis.hmget("bike:1", "model", "price");
System.out.println(res5); // [Deimos, 4972]
//对price这个属性进行累加操作
Long res6 = jedis.hincrBy("bike:1", "price", 100);
System.out.println(res6); // 5072
Long res7 = jedis.hincrBy("bike:1", "price", -100);
System.out.println(res7); // 4972
大多数Redis的散列命令都是O(1)。少数命令-例如HKEYS,HVALS和HGETALL-是O(n),其中n是字段-值对的数量。
js
//获取bike:1对应的数据所有属性
Set<String> hkeys = jedis.hkeys("bike:1");
hkeys.parallelStream().forEach(x -> System.out.println(x)); // model,brand,type,price
//获取bike:1对应的数据所有属性所对应的值
List<String> hvals = jedis.hvals("bike:1");
hvals.parallelStream().forEach(x -> System.out.println(x));
//是获取bike:1所有的值,并以Map形式返回
Map<String, String> stringStringMap = jedis.hgetAll("bike:1");
sorted sets
Redis的有序集合是由唯一字符串(成员)组成的集合,这些字符串按照关联得分进行排序。如果多个字符串具有相同的得分,则这些字符串将按字典顺序进行排序。有序集合的一些用例包括:
- 排行榜。例如,您可以使用有序集合轻松维护大型在线游戏中的最高分数列表。
- 速率限制器。特别是,您可以使用有序集合构建滑动窗口速率限制器,以防止过多的API请求。
js
//zadd与sadd类似,但是多了个score分数
Long zadd = jedis.zadd("xpc", 1940, "Alan Kay");
jedis.zadd("xpc", 1940, "Alan Kay");
jedis.zadd("xpc",1957,"Sophie Wilson");
jedis.zadd("xpc",1953,"Richard Stallman");
jedis.zadd("xpc",1949,"Yukihiro Matsumoto");
Set<String> zrange = jedis.zrange("xpc", 0, -1);
//这里就会按照sacore分数从小到大排序输出,这里切记不要使用多线程
zrange.stream().forEach(x -> System.out.println(x));
//这里就会按照sacore分数从大到小排序输出,这里切记不要使用多线程
Set<String> zrevrange = jedis.zrevrange("xpc", 0, -1);
zrevrange.stream().forEach(x -> System.out.println(x));
//拿到分数在1945~1953范围内的所有数据
Set<String> xpc = jedis.zrangeByScore("xpc", 1945, 1953);
xpc.stream().forEach(x -> System.out.println(x));
//zrank可以返回这个元素在集合中的索引位置,索引从0开始,如果没有这个元素,就返回null
Long zrank = jedis.zrank("xpc", "Richard Stallman");
//也是返回元素在集合中的索引位置,不过是按照score从大到小
Long zremrank = jedis.zrevrank("xpc", "Richard Stallman")
大多数排序集操作的时间复杂度为O(log(n)),其中n是成员的数量。
当使用ZRANGE命令返回大量结果时(例如,在数万或更多结果中),需要谨慎。此命令的时间复杂度为O(log(n) + m),其中m是返回的结果数量。
最后
给大家分享一个不错好课【剑指Java面试-Offer直通车 】链接: pan.baidu.com/s/1tSZdwcHv... 提取码: 25qw
更多优质好课,前端,后端,大数据,人工智能,高并发,企业级项目,慕课网,极客时间,拉勾教育,图灵教育,马士兵教育,享学,小马哥,咕泡,逻辑教育,黑马。尚硅谷,开课吧,网易云课堂,51CTO,龙果学院,等几十个机构优质好课。加:BaoJHao 获取