?
? ? 提到List,我們第一時間想到的就是鏈表。但是在Redis中,List更像是一種雙端隊列,例如C++中的deque。它可以快速高效的對頭部和尾部進行插入和刪除操作。本片文章主要對List列表的相關命令進行詳解,希望本篇文章會對你有所幫助。
文章目錄
一、List簡介
二、相關命令
LPUSH
LRANGE
LPUSHX
RPUSH 和 RPUSHX
LPOP 和 RPOP
LINDEX
LINSER
LLEN
LREM
LTRIM
LSET
BLPOP 和 BRPOP
三、小結
🙋?♂??作者:@Ggggggtm?🙋?♂?
👀?專欄:Redis 👀
💥?標題:Redis常用命令——List篇💥
????寄語:與其忙著訴苦,不如低頭趕路,奮路前行,終將遇到一番好風景???
一、List簡介
? 列表類型是用來存儲多個有序的字符串,如下圖所示,a、b、c、 d、e五個元素從左到右組成了一個有序的列表,列表中的每個字符串稱為元素(element) ,一個列表最多可以存儲2^32-1個元素。在Redis 中,可以對列表兩端插入(push)和彈出 (pop),還可以獲取指定范圍的元素列表、獲取指定索引下標的元素等。列表是一種比較靈活的數據結構,它可以充當棧和隊列的角色,在實際開發上有很多應用場景。
? Redis中的List還是有別于其他的鏈表的,其特點如下:
- 列表中的元素是有序的,這意味著可以通過索引下標獲取某個元素或者某個范圍的元素列表,例如要獲取上圖的第5個元素,可以執行lindex user:1:messages 4或者倒數第1個元素,lindexuser:1:messages -1就可以得到元素e。
- 區分獲取和刪除的區別,例如上圖中的lrem 1 b是從列表中把從左數遇到的前1個b元素刪除,這個操作會導致列表的長度從5變成4;但是執行lindex 4只會獲取元素,但列表長度是不會變化的。
- 列表中的元素是允許重復的,例如列表中包含了兩個 a 元素。
? 注意:上述提到列表是有序的,這里的有序并非只的是大小的有序,而是指的相對順序是有序的,也就是相對順序改變了,那么該列表就與原列表不同了!
? 提到列表中的元素可以重復,那么我們就應該想到Hash是不允許有重復的 field 的,同時我們在設置String時,其對應的key也是不可以重復的。
二、相關命令
LPUSH
??LPUSH命令是用于將一個或多個值插入到列表的頭部。語法:
LPUSH key value [value ...]
? 返回值為插入完成后,列表的長度。具體如下:
LRANGE
??LRANGE命令是用于獲取列表中指定范圍內的元素。語法:
LRANGE key start stop
??參數:
- key: 列表的鍵名。
- start: 起始索引,從0開始計數(包含該索引處的元素)。
- stop: 結束索引,從0開始計數(包含該索引處的元素)。
? 返回值: 指定范圍內的元素構成的列表。注意:這里的索引可以為負數,其中-1為該鏈表的最后一個元素,我們也可以把 -1 看成 len - 1。具體我們看如下實例:
? 其實這里有一個問題:假如我們給的索引查過了列表的范圍,那么Redis還能夠正確返回對應的值嗎?我們看如下情況:
LPUSHX
? LPUSHX命令是用于將一個值插入到已存在的列表頭部(左側)。其用法與LPUSH一樣,唯一差別就是如果該鏈表不存在,那么就插入失敗。簡單來說:若指定的key不存在,則LPUSHX命令不會進行任何操作,返回值為0。這與LPUSH命令的區別在于,LPUSH命令在key不存在時會創建一個空列表并執行插入操作。具體如下:
RPUSH 和 RPUSHX
? 學完LPUSH 和 LPUSHX后,那么RPUSH 和 RPUSHX就相當容易了。LPUSH就是進行頭插,RPUSH是尾插。其他兩者的用發、語義等全部一樣。這里就不再過多演示,大家可自行練習。
LPOP 和 RPOP
? LPOP是頭刪, RPOP是尾刪。其語法格式:
LPOP key RPOP key
- LPOP和RPOP命令都是用于移除并返回列表的第一個或最后一個元素。
- 如果列表不存在,這兩個命令將返回nil。
- 如果存在,那么返回所刪除的元素。
- 這兩個命令的時間復雜度均為O(1),因此能夠在常數時間內完成操作。
- 通過使用LPOP和RPOP命令,可以方便地實現先進先出(FIFO)或者后進先出(LIFO)的數據結構。
? 下面我們看一下具體實例:
LINDEX
? LINDEX命令用于獲取列表中指定索引位置的元素。其基本語法為:
LINDEX key index
? 其中,key是存儲列表的鍵名,index是要獲取元素的索引。索引從0開始,負數索引表示從列表末尾開始倒數。如果是非法下表,那么返回nil。具體實例如下:
? 注意,此操作的時間復雜度為O(n),并不是O(1)。
LINSER
? LINSERT命令用于向列表中特定元素的前面或后面插入新元素。其語法如下:
LINSERT key BEFORE|AFTER pivot value
? 其中,key是列表的鍵名,pivot是列表中的某個元素,value是要插入的新元素。BEFORE和AFTER是指定插入位置的關鍵詞,表示在pivot元素之前或之后進行插入。其返回值為插入成功的列表的長度。具體如下:
LLEN
??LLEN命令用于返回列表鍵的長度的命令。語法:
LLEN key
? 參數:
- key: 要獲取長度的列表鍵名。
? 返回值:
- 列表的長度,如果鍵不存在,則返回0。
? 該命令較為簡單,我們直接看實例:
LREM
? LREM命令是用于移除列表中與給定值相等的元素的命令。具體而言,它可以從列表中刪除指定數量的與給定值相等的元素。其語法:
LREM key count value
? 參數:
- key: 要操作的列表鍵名。
- count: 指定刪除元素的數量,可以為正數、負數或零。
- 當count為正數時,表示從列表頭部開始向尾部搜索,并移除與value相等的元素,直到數量達到count為止。
- 當count為負數時,表示從列表尾部開始向頭部搜索,并移除與value相等的元素,直到數量達到count的絕對值為止。
- 當count為零時,表示移除所有與value相等的元素。
- value: 要移除的元素的值。
? 返回值:
- 被移除的元素數量。
? 我們結合下述例子來理解一下。首先創建一個新的列表,其中包含的元素如下:
??
? 然后我們從左往右刪除3個1,具體如下:
? 我們再次從右向左刪除3個2,具體如下:
? 最后我們刪除所有的3,具體如下:
LTRIM
? LTRIM命令是用于修剪存儲在列表(List)數據結構中的元素。該命令可以刪除列表中指定范圍以外的所有元素,并保留指定范圍內的元素。語法:
LTRIM key start stop
? 其中,key是要操作的列表的鍵名,start和stop是要保留的元素的起始索引和結束索引(包含在內)。索引從0開始,負數索引表示從列表末尾開始計算。具體如下:
LSET
?LSET命令用于設置列表(List)數據結構中指定索引位置的元素的值。該命令可以幫助你更新列表中任意位置的元素。?語法為:
LSET key index value
? 其中,key是要操作的列表的鍵名,index是要設置的元素的索引位置,value是要設置的新值。我們來看一下實例:
? 注意,該命令的時間復雜度為O(n)。
BLPOP 和 BRPOP
??BLPOP命令是用于阻塞式(Blocking)左端彈出操作的命令,它用于從一個或多個列表中取出最左邊(頭部)的元素,并返回該元素及其所屬列表的鍵名。
? 問題來了:什么是阻塞式彈出呢?當有至少一個列表包含元素時,BLPOP會立即彈出并返回最左邊的元素和其所屬列表的鍵名;如果所有給定的列表都為空,則BLPOP會阻塞等待直到超時時間為止。簡單來說就是如果列表為空,那么就會阻塞,之后有元素后會再被喚醒!但阻塞版本會根據timeout,阻塞一段時間,期間Redis可以執行其他命令,但要求執行該命令的客戶端會表現為阻塞狀態。其語法:
BLPOP key [key ...] timeout
? 下面我們看一個實例:
? 上述key對應的value鏈表為空,所以被阻塞了。當我們從另一個客服端向此插入后,就會立刻返回:
? 那要是嘗試獲取多個列表的key呢??多個key對應多個list,這多個list哪個有元素了,就會返回哪個元素。如果多個客戶端同時多一個鍵執行pop,則最先執行命令的客戶端會得到彈出的元素。具體看如下實例:
? 從上述的返回值中我們就能能看出來是彈出的那個list的元素。實際上BRPOP和BLPOP是一樣的,這里就不再過多解釋!
三、小結
? 有關列表的命令已經介紹完畢,下圖是這些命令的作用和時間復雜度,可以用來做參考。