你必须非常努力,才能看起来毫不费力!

微信搜索公众号[ CodePlayer ],一起From Zero To Hero !

前言

Redis 中的列表(List)类型,底层是由双端队列实现,既可以作为队列,也可以作为栈。这种结构可以方便的在头尾存取元素,即使列表中已经存在了百万条记录,也能在常量时间内完成。列表也可以使用数组来实现,数组的优点是可以在常量时间内返回给定索引位置的值,但是会有空间浪费问题,需要提前分配内存,同时需考虑扩容缩容问题。Redis作为一个数据库,需要高效的把元素插入到超长列表,因此底层结构使用双端队列。下面我们就来学习List相关命令吧!

image-20210711210752194

LPUSH

可用版本:>= 1.0.0

时间复杂度: O(N),N为给定元素的个数

2.4.0版本之前只接受插入一个元素

命令格式

1
LPUSH key element [element ...]

命令描述

  • 将一个或多个元素插入到表头
  • 给定多个元素时,依次插入到表头,最终最后的一个元素为表头
  • key不存在时,会先创建一个空列表
  • key对应的value类型不是list时,返回error

返回值

常数值:插入元素后的列表长度

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 插入多个值,最后的在表头
127.0.0.1:6379> lpush mylist hello world
(integer) 2

# 依次返回表头到表尾的值
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"

# key对应的value不是list类型,报错
127.0.0.1:6379> set user:01 zhangsan
OK
127.0.0.1:6379> lpush user:01 hello
(error) WRONGTYPE Operation against a key holding the wrong kind of value

LPUSHX

可用版本:>= 2.2.0

时间复杂度: O(N),N为给定元素的个数

4.0版本之前只接受一个元素

命令格式

1
LPUSHX key element [element ...]

命令描述

只有当key存在,且对应value为列表类型时,才会将元素插入至表头

返回值

常数值:插入元素后的列表长度

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
127.0.0.1:6379> lpush mylist hello
(integer) 1

# key对应的list存在时,插入成功
127.0.0.1:6379> lpushx mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"

# list不存在,插入失败
127.0.0.1:6379> lpushx otherlist hello
(integer) 0
127.0.0.1:6379> lrange otherlist 0 -1
(empty array)

RPUSH

可用版本:>= 1.0.0

时间复杂度: O(N),N为给定元素的个数

2.4.0版本之前只接受一个元素

命令格式

1
RPUSH key element [element ...]

命令描述

  • 将一个或多个元素插入到表尾
  • 给定多个元素时,依次插入到表尾,最终最后的一个元素为表尾
  • key不存在时,会先创建一个空列表
  • key对应的value类型不是list时,返回error

返回值

常数值:插入元素后的列表长度

示例

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> flushdb
OK

# 依次插入到表尾,最终"world"为表尾
127.0.0.1:6379> rpush mylist hello world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"

RPUSHX

可用版本:>= 2.2.0

时间复杂度: O(N),N为给定元素的个数

4.0版本之前只接受一个元素

命令格式

1
RPUSHX key element [element ...]

命令描述

只有当key存在,且对应value为列表时,才会将元素插入至表尾

返回值

常数值:插入元素后的列表长度

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> rpush mylist hello
(integer) 1

# key对应的list存在
127.0.0.1:6379> rpushx mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"

# key不存在
127.0.0.1:6379> rpushx otherlist hello
(integer) 0
127.0.0.1:6379> lrange otherlist 0 -1
(empty array)

LPOP

可用版本:>= 1.0.0

时间复杂度: O(N),N为返回元素的个数

6.2.0版本开始支持count参数,支持返回多个元素

命令格式

1
LPOP key [count]

命令描述

  • 从表头弹出一个元素,相当于移除一个元素
  • 如果指定count参数,执行count次弹出操作(依赖列表长度)
  • 当list元素弹出完时,相当于删除了该key

返回值

  • 没指定count参数时:返回表尾第一个元素值或者nil(key不存在时)
  • 指定count参数时:返回弹出的元素列表或者nil(key不存在时)

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
127.0.0.1:6379> flushdb
OK

# 添加三个元素
127.0.0.1:6379> lpush mylist one two three
(integer) 3

# 弹出一个,剩余两个
127.0.0.1:6379> lpop mylist
"three"

# 指定count为3,但是list中只剩余两个元素
127.0.0.1:6379> lpop mylist 3
1) "two"
2) "one"

# 全部弹出,相当于删除了key和list
127.0.0.1:6379> lrange mylist 0 -1
(empty array)
127.0.0.1:6379> lpushx mylist one
(integer) 0
127.0.0.1:6379> exists mylist
(integer) 0

RPOP

可用版本:>= 1.0.0

时间复杂度: O(N),N为返回元素的个数

6.2.0版本开始支持count参数,支持返回多个元素

命令格式

1
RPOP key [count]

命令描述

  • 从表尾弹出一个元素,相当于移除一个元素
  • 如果指定count参数,执行count次弹出操作(依赖列表长度)
  • 当list元素弹出完时,相当于删除了该key

返回值

  • 没指定count参数时:返回表头第一个元素值或者nil(key不存在时)
  • 指定count参数时:返回弹出的元素列表或者nil(key不存在时)

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush mylist one two three
(integer) 3

# 表尾弹出一个元素,剩余两个
127.0.0.1:6379> rpop mylist
"one"

# 弹出3个元素(列表中只剩两个)
127.0.0.1:6379> rpop mylist 3
1) "two"
2) "three"

# 弹出完毕,key不存在了
127.0.0.1:6379> exists mylist
(integer) 0
127.0.0.1:6379> rpushx mylist one
(integer) 0

RPOPLPUSH

可用版本:>= 1.2.0

时间复杂度: O(1)

自6.2.0,该命令已废弃,建议使用 LMOVE,见下个命令

命令格式

1
RPOPLPUSH source destination

命令描述

  • 从source表尾弹出一个元素,插入到destination表头
  • 如果source不存在,不会执行操作
  • 如果source和destination是同一个,相当于把表尾数据移到表头的旋转操作

返回值

  • 字符串:弹出的元素值

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 准备数据
127.0.0.1:6379> LPUSH firstlist 1 2 3 4
(integer) 4
127.0.0.1:6379> lrange firstlist 0 -1
1) "4"
2) "3"
3) "2"
4) "1"

# 执行 RPOPLPUSH 移动数据
127.0.0.1:6379> RPOPLPUSH firstlist otherlist
"1"

# 验证两个列表数据
127.0.0.1:6379> lrange firstlist 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> lrange otherlist 0 -1
1) "1"

# 再次执行 RPOPLPUSH
127.0.0.1:6379> RPOPLPUSH firstlist otherlist
"2"
127.0.0.1:6379> lrange firstlist 0 -1
1) "4"
2) "3"
127.0.0.1:6379> lrange otherlist 0 -1
1) "2"
2) "1"


# 验证同一个列表
127.0.0.1:6379> LPUSH mylist 4 3 2 1
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

# 4 被旋转到了表头
127.0.0.1:6379> RPOPLPUSH mylist mylist
"4"
127.0.0.1:6379> lrange mylist 0 -1
1) "4"
2) "1"
3) "2"
4) "3"

LMOVE

可用版本:>= 6.2.0

时间复杂度: O(1)

命令格式

1
LMOVE source destination LEFT|RIGHT LEFT|RIGHT

命令描述

  • 从source表尾/表头弹出元素,插入到destination的表尾/表头

    例如source=[a,b,c], destination=[x,y,z],执行 LMOVE source destination RIGHT LEFT, 相当于将source表尾的数据移动到destination表头,此时 source=[a,b], destination=[c,x,y,z]

  • 如果source不存在,不会执行操作

  • 如果source和destination是同一个列表,那么相当于列表旋转操作或者无操作(最后两个参数都为LEFT或RIGHT)

  • LMOVE LEFT RIGHT 等价于 RPOPLPUSH

返回值

  • 字符串:弹出的元素值

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# first 列表中的元素
127.0.0.1:6379> lrange first 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

# 执行 lmove right left, 将first表尾元素移动到second表头
127.0.0.1:6379> lmove first second right left
"4"
127.0.0.1:6379> lrange first 0 -1
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> lrange second 0 -1
1) "4"

# 执行lmove left right,将first表头元素移动到second表尾
127.0.0.1:6379> lmove first second  left right
"1"
127.0.0.1:6379>  lrange first 0 -1
1) "2"
2) "3"
127.0.0.1:6379>  lrange second 0 -1
1) "4"
2) "1"

LRANGE

可用版本:>= 1.0.0

时间复杂度: O(S+N),S为start至表头的偏移量,N为元素范围

命令格式

1
LRANGE key start stop

命令描述

  • 返回列表指定区间内的元素,区间以偏移量 startstop 指定
  • 下标从0开始,0表示第一个元素,1表示第二个元素
  • 也可以使用负数表示,-1表示最后一个元素,-2表示倒第二个元素
  • 指定的区间,左右都是闭区间,即[start,stop]
  • start和stop超出列表范围不会报错,如果start超出列表范围,会返回空列表;如果stop超出列表范围,遍历到最后一个元素就会停止

返回值

  • 列表:指定范围内的元素列表

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
127.0.0.1:6379> rpush rangelist 1 2 3
(integer) 3

127.0.0.1:6379> lrange rangelist 0 0
1) "1"

127.0.0.1:6379> lrange rangelist 0 2
1) "1"
2) "2"
3) "3"

# stop 超出列表范围
127.0.0.1:6379> lrange rangelist 0 5
1) "1"
2) "2"
3) "3"

# start 超出列表范围
127.0.0.1:6379> lrange rangelist 3 5
(empty array)

# -1 为最后一个元素
127.0.0.1:6379> lrange rangelist 0 -1
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> lrange rangelist -3 -1
1) "1"
2) "2"
3) "3"

# start>stop
127.0.0.1:6379> lrange rangelist -1 -2
(empty array)

LINDEX

可用版本:>= 1.0.0

时间复杂度: O(N),N为访问到该索引需遍历的元素个数,对于表头表尾N=1

命令格式

1
LINDEX key index

命令描述

  • 根据索引,返回列表中对应的元素值
  • 0为第一个元素索引,1表示第二个元素索引,以此类推
  • 也可以使用负数表示,-1表示最后一个,-2表示倒第二个,以此类推

返回值

  • 字符串:索引对应的元素值;索引超出列表范围,返回nil

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
127.0.0.1:6379> rpush mylist a b c d
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> lindex mylist 0
"a"
127.0.0.1:6379> lindex mylist 3
"d"

# 超出范围
127.0.0.1:6379> lindex mylist 4
(nil)
127.0.0.1:6379> lindex mylist -1
"d"

更多

微信公众号:CodePlayer