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) 1redis> LPUSH mylist "hello"(integer) 2redis> LRANGE mylist 0 -11) "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) 1redis> LPUSHX mylist "Hello"(integer) 2redis> LPUSHX myotherlist "Hello"(integer) 0redis> LRANGE mylist 0 -11) "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) 1redis> RPUSH mylist "hello"(integer) 2redis> LRANGE mylist 0 -11) "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) 1redis> RPUSHX mylist "Hello"(integer) 2redis> RPUSHX myotherlist "Hello"(integer) 0redis> LRANGE mylist 0 -11) "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) 1redis> RPUSH mylist "two"(integer) 2redis> RPUSH mylist "three"(integer) 3redis> LRANGE mylist 0 01) "one"redis> LRANGE mylist -3 21) "one"2) "two"3) "three"redis> LRANGE mylist -100 1001) "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 elementpivot 以該元素為基準
命令有效版本: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) 1redis> LPUSH mylist "Hello"(integer) 2redis> 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) 0redis> RPUSH list1 a b c(integer) 3redis> BLPOP list1 list2 01) "list1"2) "a"![]()
當插入任何一個元素都會返回
3.2 BRPOP
RPOP 的阻塞版本。
語法:
BRPOP key [key ...] timeout
命令有效版本:1.0.0 之后時間復雜度:O(1)返回值:取出的元素或者 nil。
?例:
redis> DEL list1 list2(integer) 0redis> RPUSH list1 a b c(integer) 3redis> BRPOP list1 list2 01) "list1"2) "c"
4.命令小節?
操作類型 | 命令 | 時間復雜度 |
添加 | rpush key value [value ...] | O(k),k 是元素個數 |
lpush key value [value ...] | O(k),k 是元素個數 | |
linsert key 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) | |
lremkey count value | O(k),k 是元素個數 | |
ltrim key start end | O(k),k 是元素個數 | |
修改 | lset key index value | O(n),n 是索引的偏移量 |
阻塞操作 | blpop brpop | O(1) |