9.Redis之list类型

list相当于链表、数据表

1.list类型基本介绍

  • 列表中的元素是有序的
  • "有序"的含义,要根据上下文区分~~
  • 有的时候,谈到有序,指的是"升序","降序”
  • 有的时候,谈到的有序,指的是, 顺序很关键~~
  • 如果把元素位置颠倒,顺序调换.
  • 此时得到的新的 List 和之前的 List 是不等价的!!
  • 同样一个词,怎么理解,务必要结合上下文,结合具体场景~~
  • 栈/堆.(数据结构的,操作系统的,M 的)
  • 同步(同步和互斥的同步,还是同步和异步的同步)

1.区分获取和删除的区别

lindex 能获取到元素的值
lrem 也能返回被删除元素的值.

2.列表中的元素是允许重复的

像 hash 这样的类型, field 是不能重复的

因为当前的 List,头和尾都能高效的插入删除元素, 就可以把这个 List 当做一个 栈/队列 来使用了

Redis 有一个典型的应用场景,就是作为消息队列

最早的时候, 就是通过 List 类型~.

后来 Redis 又提供了 stream 类 (用于消息队列)

2.list相关命令

2.1 LPUSH

将⼀个或者多个元素从左侧放⼊(头插)到 list 中。
语法:
LPUSH key element [element ...]
命令有效版本:1.0.0 之后
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的长度。
⽰例:
redis> LPUSH mylist "world"
(integer) 1
redis> LPUSH mylist "hello"
(integer) 2
redis> LRANGE mylist 0 -1
1) "hello"
2) "world"
//按照顺序,依次头插这几个元素.
//全都插入完毕,4 是在最前面的!!!
//如果 key 已经存在, 并且 key 对应的 value 类型,不是 list
//此时 lpush 命令就要报错.
//此处的序号与下标无关,序号只是标识项,描述一下顺序

2.2 LPUSHX

在 key 存在时,将⼀个或者多个元素从左侧放⼊(头插)到 list 中。不存在,直接返回
语法:
LPUSHX key element [element ...]
命令有效版本:2.0.0 之后
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。
示例:
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSHX mylist "Hello"
(integer) 2
redis> LPUSHX myotherlist "Hello"
(integer) 0
redis> LRANGE mylist 0 -1
1) "Hello"
2) "World"
redis> LRANGE myotherlist 0 -1
(empty array)

2.3 RPUSH

将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。
语法:
RPUSH key element [element ...]
命令有效版本:1.0.0 之后
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。
⽰例:
redis> RPUSH mylist "world"
(integer) 1
redis> RPUSH mylist "hello"
(integer) 2
redis> LRANGE mylist 0 -1
1) "world"
2) "hello"

 2.4 RPUSHX

在 key 存在时,将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。
语法:
RPUSHX key element [element ...]
命令有效版本:2.0.0 之后
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。
⽰例:
redis> RPUSH mylist "World"
(integer) 1
redis> RPUSHX mylist "Hello"
(integer) 2
redis> RPUSHX myotherlist "Hello"
(integer) 0
redis> LRANGE mylist 0 -1
1) "World"
2) "Hello"
redis> LRANGE myotherlist 0 -1
(empty array)

2.5 LRANGE

获取从 start 到 end 区间的所有元素,左闭右闭。
语法:
//此处的l不是left,而是list
LRANGE key start stop
命令有效版本:1.0.0 之后
时间复杂度:O(N)
返回值:指定区间的元素。
⽰例:
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> LRANGE mylist 0 0
1) "one"
redis> LRANGE mylist -3 2
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist -100 100
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist 5 10
(empty array)

2.6 LPOP

从 list 左侧取出元素(即头删)。
语法:
LPOP key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:取出的元素或者 nil。
⽰例:
redis> RPUSH mylist "one" "two" "three" "four" "five"
(integer) 5
redis> LPOP mylist
"one"
redis> LPOP mylist
"two"
redis> LPOP mylist
"three"
redis> LRANGE mylist 0 -1
1) "four"
2) "five"

2.7 RPOP

从 list 右侧取出元素(即尾删)。
语法:
RPOP key
我们所用的版本是5 不考虑
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:取出的元素或者 nil。
⽰例:
redis> RPUSH mylist "one" "two" "three" "four" "five"
(integer) 5
redis> RPOP mylist
"five"
redis> LRANGE mylist 0 -1
1) "one"
2) "two"
3) "three"
4) "four"

Redis 中的 list 是一个双端队列~~

从两头插入/删除元素都是非常高效 O(1)
搭配使用 rpush 和 lpop, 就相当于队列了

搭配使用 rpush 和 rpop, 就相当于栈了,

2.8 LINDEX

获取从左数第 index 位置的元素。
语法:
  LINDEX key index
命令有效版本:1.0.0 之后
时间复杂度:O(N),此处的N是list中元素的个数
返回值:取出的元素或者 nil。
⽰例:
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LINDEX mylist 0
"Hello"
redis> LINDEX mylist -1
"World"
redis> LINDEX mylist 3
(nil)

2.9 LINSERT

在特定位置插⼊元素。
语法:
LINSERT key <BEFORE | AFTER> pivot element
pivot 以该元素为基准
命令有效版本:2.2.0 之后
时间复杂度:O(N)
返回值:插⼊后的 list ⻓度。
⽰例:
redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"

//基准不是下标,而是元素

万一要插入的列表中,基准值,存在多个,咋办?
linsert 进行插入的时候,要根据基准值, 找到对应的位置,从左往右找,找到第一个符合基准值的位置即可.
O(N),N 表示列表的长度

2.10 LLEN

获取 list ⻓度。
语法:
LLEN key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:list 的⻓度。
⽰例:
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LLEN mylist
(integer) 2

2.11 LREM

count>0,从左往右找

count<0,从右往左找

count=0,全部删除

 2.12 LRIM

只保留区间内的数

时间复杂度是O(N),N是当前要删除的元素的个数

2.13 LSET 

 3.阻塞版命令

  • redis 中的 list 也相当于 阻塞队列 一样
  • 线程安全是通过单线程模型支持的.
  • 阻塞,则只支持"队列为空"的情况,不考虑"队列满”
  • 但阻塞版本会根据 timeout,阻塞一段时间,期间 Redis 可以执行其他命令使用 brpop 和 blpop 的时候,这里是可以显式设置阻塞时间的!!!(不一定是无休止的等待!!)【此处的 blpop 和 brpop 看起来好像耗时很久,但是实际上并不会对 redis 服务器产生负面影响!!】
  • 命令中如果设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表中可以弹出元素,命令立即返回。
    blpop 和 brpop 都是可以同时去尝试获取多个 key 的列表的元素的~~
    多个 key 对应多个 list这多个 |ist 哪个有元素了,就会返回哪个元素,
    如果多个客户端同时多一个键执行 pop,则最先执行命令的客户端会得到弹出的元素。
  • 区别
blpop 和 brpop 是 lpop 和 rpop 的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,除了:
在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理
解返回 nil,但阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执
⾏该命令的客⼾端会表现为阻塞状态(如图 2-22 所⽰)。
命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元
素,命令⽴即返回。
如果多个客⼾端同时多⼀个键执⾏ pop,则最先执⾏命令的客⼾端会得到弹出的元素。

3.1 BLPOP

LPOP 的阻塞版本。
语法:
BLPOP key [key ...] timeout
  • 此处 可以指定一个 key 或者 多个 key
  • 每个 key 都对应一个 list.
  • 如果这些 list 有任何一个非空,blpop 都能够把这里的元素给获取到. 立即返回如果这些 list 都为空, 此时就需要阻塞等待, 等待其他客户端往这些 list 中插入元素了
  • 单位是 秒(Redis 6, 超时时间允许设定成小数.Redis 5 中,超时时间,得是整数)
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:取出的元素或者 nil。
⽰例:
redis> EXISTS list1 list2
(integer) 0
redis> RPUSH list1 a b c
(integer) 3
redis> BLPOP list1 list2 0
1) "list1"
2) "a"
当插入任何一个元素都会返回

3.2 BRPOP

RPOP 的阻塞版本。
语法:
BRPOP key [key ...] timeout
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:取出的元素或者 nil。
⽰例:
redis> DEL list1 list2
(integer) 0
redis> RPUSH list1 a b c
(integer) 3
redis> BRPOP list1 list2 0
1) "list1"
2) "c"

4.命令小节 

操作类型命令时间复杂度
添加rpush key value [value ...]O(k),k 是元素个数
lpush key value [value ...]O(k),k 是元素个数
linsert key before | after pivot valueO(n),n 是 pivot 距离头尾的距离
查找lrange key start end
O(s+n),s 是 start 偏移量,n 是 start 到 end 的范围
lindex key indexO(n),n 是索引的偏移量
llen keyO(1)
删除lpop keyO(1)
rpop keyO(1)
lremkey count valueO(k),k 是元素个数
ltrim key start endO(k),k 是元素个数
修改lset key index valueO(n),n 是索引的偏移量
阻塞操作blpop brpopO(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/646058.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux(六)

Linux&#xff08;六&#xff09; 自定义头文件自定义头文件中写什么如何引入头文件条件编译条件编译作用 gcc工作原理Make 工作管理器什么是Make什么是Makefile/makefileMakefile假目标Makefile中的变量自定义变量预定义变量自动变量 Makefile中变量展开方式递归展开方式简单展…

【C++】二分查找算法

1.题目 2.算法思路 暴力解法&#xff1a;可以将数组遍历一遍&#xff0c;就可以找到。时间复杂度为O(n)。不算太差&#xff0c;可以接受。 但是有更优秀的解法&#xff1a; 就是二分查找算法。 算法的特点&#xff1a;我们所查找的“数组”具有二段性。这里的二段性不一定有…

Vue 安装vue

1、官网安装下载安装nodejs 2、安装完成后&#xff0c;通过命令查看版本,可以查看到版本 node -v npm -v 3、安装Vue CLi npm install -g vue/cli 4、创建项目,vue create test 如果遇到报错&#xff1a; ERROR Error: spawn yarn ENOENT Error: spawn yarn ENOENT at ChildP…

人工智能+跨癌种分析,能否解决医学数据样本量小的问题?【医学AI|顶刊速递|05-26】

小罗碎碎念 先说明&#xff0c;目前小罗只是硕士&#xff0c;以下个人观点很有可能不准确&#xff0c;欢迎批评指正&#xff01;&#xff01;小罗虚心听取有益建议&#xff01;&#xff01; 众所周知&#xff0c;医学数据相比于其他领域的数据来说&#xff0c;属于小样本数据。…

【仿RabbitMQ消息队列项目day4】GTest测试框架使用

一.什么是GTest? GTest是一个跨平台的 C单元测试框架&#xff0c;由google公司发布。gtest是为了在不同平台上为编写C单 元测试而生成的。 二.使用 TEST(test_case_name, test_name)&#xff1a;主要用来创建⼀个简单测试&#xff0c; 它定义了一个测试函数&#xff0c; 在这个…

【NumPy】关于numpy.sum()函数,看这一篇文章就够了

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

安卓自定义控件(视图、改造控件、通知Notification、界面绘制)

视图的构建过程 此节介绍一个视图的构建过程&#xff0c;包括&#xff1a;如何编写视图的构造方法&#xff0c;4个构造方法之间有什么区别&#xff1b;如何测量实体的实际尺寸&#xff0c;包含文本、图像、线性视图的测量方法&#xff1b;如何利用画笔绘制视图的界面&#xff…

Ubuntu22.04设置程序崩溃产生Core文件

Ubuntu22.04设置程序崩溃产生Core文件 文章目录 Ubuntu22.04设置程序崩溃产生Core文件摘要Ubuntu 生成Core文件配置1. 检查 core 文件大小限制2. 设置 core 文件大小限制3. 配置 core 文件命名和存储路径4. 重启系统或重新加载配置5. 测试配置 关键字&#xff1a; Ubuntu、 C…

跨平台之用VisualStudio开发APK嵌入OpenCV(一)

序 本篇是杂谈以及准备工作&#xff08;此处应无掌声&#xff09; 暂时不管iOS&#xff08;因为开发hello world都要年费&#xff09; 软件&#xff1a; Visual Studio 2019&#xff08;含Android SDK和NDK编译器等&#xff09; OpenCV 这是一个女仆级的系列文章&#xf…

代码随想录|Day56|动态规划 part16|● 583. 两个字符串的删除操作 ● 72. 编辑距离

583. 两个字符串的删除操作 class Solution: def minDistance(self, word1: str, word2: str) -> int: dp [[0] * (len(word2) 1) for _ in range(len(word1) 1)] for i in range(len(word1) 1): dp[i][0] i for j in range(len(word2) 1): dp[0][j] j for i in rang…

OpenStack平台Nova管理

1. 规划节点 使用OpenStack平台节点规划 IP主机名节点192.168.100.10controller控制节点192.168.100.20compute计算节点 2. 基础准备 部署的OpenStack平台 1. Nova运维命令 &#xff08;1&#xff09;Nova管理安全组规划 安全组&#xff08;security group&#xff09;是…

网上比较受认可的赚钱软件有哪些?众多兼职选择中总有一个适合你

在这个互联网高速发展的时代&#xff0c;网上赚钱似乎成了一种潮流。但是&#xff0c;你是否还在靠运气寻找赚钱的机会&#xff1f;是否还在为找不到靠谱的兼职平台而苦恼&#xff1f; 今天&#xff0c;就为你揭秘那些真正靠谱的网上赚钱平台&#xff0c;让你的赚钱之路不再迷…

1107 老鼠爱大米

solution 记录每组的最大值&#xff0c;并比较组间的最大值胖胖鼠~ #include<iostream> using namespace std; int main(){int n, m, ans, fat -1, x;scanf("%d%d", &n, &m);for(int i 0; i < n; i){ans -1;for(int j 0; j < m; j){scanf(…

Docker compose 的方式一键部署夜莺

官方安装文档&#xff1a;https://flashcat.cloud/docs/content/flashcat-monitor/nightingale-v7/install/docker-compose/ 介绍&#xff1a;夜莺监控是一款开源云原生观测分析工具&#xff0c;采用 All-in-One 的设计理念&#xff0c;集数据采集、可视化、监控告警、数据分析…

python列表元素的增减之道:删除篇

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、前言 二、删除元素的基本方法 1. 使用remove()方法 2. 使用pop()方法 3. 使用del语句…

ICML 2024 | 北大、字节提出新型双层位置编码方案,有效改善长度外推效果

在这项工作中&#xff0c;我们利用语言序列的内在分段特性&#xff0c;设计了一种新的位置编码方法来达到更好的长度外推效果&#xff0c;称为双层位置编码&#xff08;BiPE&#xff09;。对于每个位置&#xff0c;我们的 BiPE 融合了段内编码和段间编码。段内编码通过绝对位置…

从用法到源码再到应用场景:全方位了解CompletableFuture及其线程池

文章目录 文章导图什么是CompletableFutureCompletableFuture用法总结API总结 为什么使用CompletableFuture场景总结 CompletableFuture默认线程池解析&#xff1a;ForkJoinPool or ThreadPerTaskExecutor&#xff1f;ForkJoinPool 线程池ThreadPerTaskExecutor线程池Completab…

AI教母李飞飞:现在的AI根本没有主观感觉能力

通用人工智能 (AGI) 是用来描述至少在人类展示&#xff08;或可以展示&#xff09;智能的所有方面都与人类一样聪明的人工智能代理的术语。这就是我们过去所说的人工智能&#xff0c;直到我们开始创建无可否认“智能”的程序和设备&#xff0c;但这些程序和设备只在有限的领域—…

查分数组总结

文章目录 查分数组定义应用举例LeetCode 1109 题「[航班预订统计] 查分数组定义 差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。 通过这个 diff 差分数组是可以反推出原始数组 nums 的&#xff0c;代码逻辑如下&#xff1a; int res[diff.size()]; // 根…

新建一个STM32的工程

一、SMT32开发方式 1、基于寄存器的方式&#xff1a;和51单片机开发方式一样&#xff0c;是用程序直接配置寄存器&#xff0c;来达到我们想要的功能&#xff0c;这种方式最底层、最直接、效率会更高一些&#xff0c;但是STM32的结构复杂、寄存器太多&#xff0c;所以不推荐基于…