API的理解和使用——列表类型的命令

列表类型的命令及对应的时间复杂度
操作 命令 功能 时间复杂度
添加 rpush key value [value ...] 向右插入 O(k),k是元素个数
lpush key value [value....] 向左插入 O(k),k是元素个数
linsert ket before|after pivot value 指定的元素前后插入
O(n),n是pivot距离列表头或尾的距离

查找 lrange key start end 根据范围查找 O(s+n),s是start偏移量,n是start到end的范围
lindex key index 根据索引查找某个元素 O(n),n是索引的偏移量
llen key 获取列表长度 O(1)
删除 lpop key 从左弹出一个元素 O(1)
rpop key 从右弹出一个元素 O(1)
lrem key count value 删除指定元素 O(n),n是列表长度
ltrim key start end 裁剪 O(n),n是要裁剪的元素总数
修改 lset key index newvalue 根据索引修改元素的值 O(n),n是索引的偏移量
阻塞操作 blpop key [key ...] timeout 从左弹出阻塞 O(1)
brpop key [key...] timeout 从右弹出阻塞 O(1)

列表(list)类型是用来存储多个有序的字符串,如下图所示,a、b、c、d、e五个元素从左到右组成了一个有序的列表,

列表中的每个字符串称为元素(element),一个列表最多可以存储2**32 -1个元素。

在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围内的元素、获取指定索引下标的元素等。

列表是一种比较灵活的数据结果,它可以充当栈和队列的角色。

列表类型有两个特点:

第一、列表种的元素是有序的,这就意味着可以通过索引下标获取某个元素或着某个范围内的元素列表。

例如要获取下图中的第5个元素,可以执行lindex user:1:message 4(索引从0算起)就可以得到元素e。

第二、列表中的元素是可以重复的

这两个特点在后面介绍集合和有序集合后,会显得更加突出。

下面介绍列表的5个操作命令。

1.添加操作

(1)从右边值插入元素

命令:rpush key value [value ... ]

127.0.0.1:6379> rpush list:1 a b c   #一直向右插入
(integer) 3
127.0.0.1:6379> lrange list:1 0 -11) "a"
2) "b"
3) "c"

(2)从左边取值插入元素

命令:lpush key value [value ... ]

127.0.0.1:6379> lpush list:2 a b c   #一直向左插入
(integer) 3
127.0.0.1:6379> lrange list:2 0 -1
1) "c"
2) "b"
3) "a"

如果对于上面的插入方法还不够清晰,那么可以看下下面这个例子:

127.0.0.1:6379> lrange list:1 0 -1
1) "python"
2) "b"
127.0.0.1:6379> lpush list:1 a1 a2 a3
(integer) 5
127.0.0.1:6379> rpush list:1 c1 c2 c3
(integer) 8
127.0.0.1:6379> lrange list:1 0 -1
1) "a3"
2) "a2"
3) "a1"
4) "python"
5) "b"
6) "c1"
7) "c2"
8) "c3"

(3)向某个元素前或着后插入元素

命令:linsert key before|after pivot value

linsert命令会从列表中找到等于pivot的元素,在其前(before)或者后(after)插入一个新的元素value:

127.0.0.1:6379> linsert list:1 before b python
(integer) 4   #当前长度为4
127.0.0.1:6379> lrange list:1 0 -1
1) "a"
2) "python"
3) "b"
4) "c"

2.查找

(1)获取指定范围内的元素列表

命令:lrange key start end

lrange操作会获取列表指定索引范围所有的元素。索引下标有两个特点:

第一,索引下标从左到右分别是0到N-1,但是从右到左分别是-1到-N。

第二,lrange中的end选项包含了自身,这和许多编程语言不包含end不大相同。

127.0.0.1:6379> lrange list:1 0 -1  #第一个到最后一个,就是所有
1) "a"
2) "python"
3) "b"
4) "c"
127.0.0.1:6379> lrange list:1 1 2   #第二个和第三个
1) "python"
2) "b"

(2)获取列表指定索引下标的元素

命令:lindex key index

127.0.0.1:6379> lrange list:1 0 -1
1) "a"
2) "python"
3) "b"
4) "c"
127.0.0.1:6379> lindex list:1 1   #获取第二个元素
"python"

(3)获取列表长度

命令:llen key

127.0.0.1:6379> lrange list:1 0 -1
1) "a"
2) "python"
3) "b"
4) "c"
127.0.0.1:6379> llen list:1
(integer) 4

3.删除

(1)从列表左侧弹出元素

命令:lpop key

127.0.0.1:6379> lrange list:1 0 -1
1) "a"
2) "python"
3) "b"
4) "c"
127.0.0.1:6379> lpop list:1
"a"
127.0.0.1:6379> lrange list:1 0 -1
1) "python"
2) "b"
3) "c"

(2)从列表右侧弹出元素

命令:rpop key

127.0.0.1:6379> lrange list:1 0 -1
1) "python"
2) "b"
3) "c"
127.0.0.1:6379> rpop list:1
"c"
127.0.0.1:6379> lrange list:1 0 -1
1) "python"
2) "b"

(3)删除指定元素

命令:lrem key count value

lrem命令会从列表中找到等于value的元素进行删除,根据count的不同分为三种情况:

count > 0:从左到右,删除最多count个元素,前提是要有。

count = 0:删除所有

count < 0:从右到左,删除最多count绝对值个元素

127.0.0.1:6379> lrange list:1 0 -1
 1) "d"
 2) "c"
 3) "b"
 4) "a"
 5) "c"
 6) "b"
 7) "a"
 8) "b"
 9) "a"
10) "python"
11) "a"
12) "b"
13) "a"
14) "b"
15) "c"
16) "a"
17) "b"
18) "c"
19) "d"
127.0.0.1:6379> lrem list:1 3 a  #从左边开始删
(integer) 3
127.0.0.1:6379> lrange list:1 0 -1
 1) "d"
 2) "c"
 3) "b"
 4) "c"
 5) "b"
 6) "b"
 7) "python"
 8) "a"
 9) "b"
10) "a"
11) "b"
12) "c"
13) "a"
14) "b"
15) "c"
16) "d"
127.0.0.1:6379> lrem list:1 -3 a  #从右边开始删
(integer) 3
127.0.0.1:6379> lrange list:1 0 -1
 1) "d"
 2) "c"
 3) "b"
 4) "c"
 5) "b"
 6) "b"
 7) "python"
 8) "b"
 9) "b"
10) "c"
11) "b"
12) "c"
13) "d"
127.0.0.1:6379> lrem list:1 0 c   #删除所有
(integer) 4
127.0.0.1:6379> lrange list:1 0 -1
1) "d"
2) "b"
3) "b"
4) "b"
5) "python"
6) "b"
7) "b"
8) "b"
9) "d"

lrem会从一个方向开始,匹配count个目标元素,如果遍历了所有元素,没有找到,那就会删除已有的。

127.0.0.1:6379> lrange list:1 0 -1
1) "d"
2) "b"
3) "b"
4) "b"
5) "python"
6) "b"
7) "b"
8) "b"
9) "d"
127.0.0.1:6379> lrem list:1 4 d
(integer) 2

(4)按照索引范围修剪列表

命令:ltrim key start end

ltrim会删除范围之外的所有元素:

127.0.0.1:6379> lrange list:1 0 -1
1) "b"
2) "b"
3) "b"
4) "python"
5) "b"
6) "b"
7) "b"
127.0.0.1:6379> ltrim list:1 2 -3  #保留中间3个
OK
127.0.0.1:6379> lrange list:1 0 -1
1) "b"
2) "python"
3) "b"

4.修改

命令:lset key index newValue

127.0.0.1:6379> lrange list:1 0 -1
1) "b"
2) "python"
3) "b"
127.0.0.1:6379> lset list:1 -1 NB  #将最后一个修改为NB
OK
127.0.0.1:6379> lrange list:1 0 -1
1) "b"
2) "python"
3) "NB"

5.阻塞操作

命令:

blpop key [key ... ] timeout
brpop key [key ...] timeout

参数说明:

key [key ...]:多个列表的键

timeout:阻塞时间(单位为秒)

(1)列表不为空:客户端会立即返回

127.0.0.1:6379> lrange list:1 0 -1
1) "b"
2) "python"
3) "NB"
127.0.0.1:6379> blpop  list:1 timeout = 3  #从左边取值
1) "list:1"
2) "b"
127.0.0.1:6379> brpop  list:1 timeout = 3  #从右边取值
1) "list:1"
2) "NB"
127.0.0.1:6379> lrange list:1 0 -1
1) "python"

127.0.0.1:6379> brpop  list:1 timeout = 0
1) "list:1"
2) "python"

当列表不为空的时候,不论时间设置为几秒都会立即返回一个值。

(2)列表为空:如果timeout = 3,那么客户端要等到3秒后返回,如果timeout = 0,那么客户端一直阻塞等下去:

127.0.0.1:6379> brpop  list:1 timeout = 3
(nil)
(3.01s)
127.0.0.1:6379> brpop  list:1 timeout = 0
...等待中...

如果在此期间添加了元素,客户端会立即返回:

#另一台机器
127.0.0.1:6379> lpush list:1 a b c
(integer) 3  ——》列表 c b a
#被阻塞那台
127.0.0.1:6379> brpop  list:1 timeout = 0
1) "list:1"   #从右边取值所以为a
2) "a"
(108.39s)  #已经等了100多秒

在使用brpop时,有两点需要注意。

第一,如果多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端会立即返回:

127.0.0.1:6379> brpop  list:1 list:2 list:3 timeout = 0
...等待中...

此时在另一客户端list:3插入元素:

127.0.0.1:6379> brpop  list:1 list:2 list:3 timeout = 0
1) "list:3"
2) "a"
(8.90s)

在键元素的个数不大时,并不能体现brpop是从左到右遍历键。

第二,如果多个客户端对同一个键执行brpop,那么最先执行brpop命令的客户端先返回值

客户端1
127.0.0.1:6379> brpop list:1 timeout = 0
...等着...

客户端2
127.0.0.1:6379> brpop list:1 timeout = 0
...等着...

在另一台机器上往list:1上插入一个元素:

先请求的的会得到值,另一台等着
127.0.0.1:6379> brpop list:1 timeout = 0
1) "list:1"
2) "a1"
(133.99s)
时间: 2024-10-11 04:34:37

API的理解和使用——列表类型的命令的相关文章

python列表类型

列表类型简介 列表类型是一个容器,它里面可以存放任意数量.任意类型的数据. 例如下面的几个列表中,有存储数值的.字符串的.内嵌列表的.不仅如此,还可以存储其他任意类型. >>> L = [1, 2, 3, 4] >>> L = ["a", "b", "c", "d"] >>> L = [1, 2, "c", "d"] >>

玩一把redis源码(一):为redis添加自己的列表类型

2019年第一篇文档,为2019年做个良好的开端,本文档通过step by step的方式向读者展示如何为redis添加一个数据类型,阅读本文档后读者对redis源码的执行逻辑会有比较清晰的认识,并且可以深入理解redis 源码中关于链表数据结构的使用,写这篇文档作者获益良多,阅读系统软件源码的兴趣也大大提高. 同时也再次感受到良好的基础是深入学习的前提.特别强调本文档仅用于学习,并非是要修改redis源码. 建议读者阅读本文档时实际动手敲一下代码,然后翻阅下redis源码,debug下redi

使用 redis ( list列表类型操作)

list 数据类型 列表类型 list 类型是一个双向操作 从链表的头部或者尾部添加删除元素 list 既可以用作栈 也可以用作队列 list 链表的类型应用场合: 获取最新的 10 个用户的信息 select * from user order by logintime desc limit 10; 数据不复杂 但是 对数据库的负载比较大 如给关键字 logintime 设置索引 耗费资源 用 redis 通过 list 链表实现以上功能 在 list 链表中只保留最新的10个数据 每一次进来

强制理解背诵知识列表

u 强制理解背诵知识列表 l 操作系统:进程,线程:死锁:Linux 三十条命令,PV 原语,生产者消费者,银行家算法,信号量算法 l 计算机网络:TCP,HTTP,Web 服务器 l Java:五十个关键字:多线程,线程池,线程安全:内存分配:二十三种设计模式:代码健壮性:Spring 开源框架 l 数据库:复杂查询的 SQL 语句,SQL 优化:死锁,事务回滚,解锁:视图,索引 l 算法:排序算法:KMP 算法:Aho-Corasick 算法 u 时间:2017年02月21日-2017年05

Redis学习之列表类型详解

本文和大家分享的主要是redis的列表类型相关内容,一起来看看吧,希望对大家学习redis有所帮助. 列表类型,可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段 列表类型内部是使用双向链表实现的,所以向列表两端添加元素的时间复杂度是 o(1),获取越接近两端的元素速度就越快 链表的代价是通过索引访问元素比较慢 向列表两端添加元素 向列表左边添加元素,返回增加后列表的长度 LPUSH key value1 value2 127.0.0.1:6379> LPUS

#定义一个方法get_num(num),num参数是列表类型,判断列表里面的元素为数字类型。其他类型则报错,并且返回一个偶数列表:(注:列表里面的元素为偶数)。

1 #定义一个方法get_num(num),num参数是列表类型,判断列表里面的元素为数字类型.其他类型则报错,并且返回一个偶数列表:(注:列表里面的元素为偶数). 2 def get_num(num): 3 if type(num)!= list: 4 return '您传入的不是列表!' 5 else: 6 for i in num: 7 if not isinstance(i,int): 8 return '请全部传入整数!' 9 return list(filter(lambda x:x

《Effective Modern C++》翻译--条款2: 理解auto自己主动类型推导

条款2: 理解auto自己主动类型推导 假设你已经读过条款1关于模板类型推导的内容,那么你差点儿已经知道了关于auto类型推导的所有. 至于为什么auto类型推导就是模板类型推导仅仅有一个地方感到好奇.那是什么呢?即模板类型推导包含了模板.函数和參数,而auto类型判断不用与这些打交道. 这当然是真的.可是没关系. 模板类型推导和auto自己主动类型推导是直接匹配的. 从字面上看,就是从一个算法转换到还有一个算法而已. 在条款1中.阐述模板类型推导採用的是常规的函数模板: template<ty

1-2:数据类型之元组、列表类型

一.元组的概念: 前面我们学过数字类型,字符串类型,它们都代表一个元素!1.元组是包含多个元素的类型,元素之间用逗号分隔. t1 = 123,456,"hello" 2.元组可以使空的,t2 = ()3.元组包含一个元素: t3 = 123,4.元组外层可以使用括号,也可以不使用 二.元组的三大特点: 1.元组中元素可以使不同类型.元组也可以作为另一个元组的元素,只是此时作为元素的元组要加上括号来区分,从而避免歧义! t3 = 123456,("hello",&qu

python中常用的列表类型内建函数

1.list.append(obj)         向列表中添加一个对象obj list = ['apple', 'pear', 'orange'] >>> list.append('apple') >>> list ['apple', 'pear', 'orange', 'apple'] 2.list.count(obj)             返回一个对象obj在列表中出现的次数 >>> list.count('apple') 2 3.list