redis中的list类型有点类似于编程语言中的数组,list类型如下图所示,实际上是一种双向链表结构,通过lpush、lpop、rpush、rpop这几个命令来控制链表中数据出入,所以list类型可以用作栈,也可以用作队列一样。
redis链表list类型
从元素插入和删除的效率来看,如果从链表的两头插入或删除元素,会非常的高效,即使链表中已经存储了上百万条的记录,也可以在很短的时间内完成。然而需要说明的是,如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。相信对于有良好数据结构基础的开发者而言,这一点并不难理解。
因此, redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。
以下是链表类型(list)的一些常用命令:
1.【 lpush key value 】 往队列头部插入一个元素
2.【 rpush key value 】 从尾部插入一个元素
3.【 lpop key 】 从队列头部删掉一个元素
4.【 rpop key 】 从队列尾部删掉一个元素,并返回被删除元素的值
5.【 llen 】 返回队列的长度,即里面有多少个元素。不存在key返回0,不为队列类型的key会返回报错。
6.【 lrange key start end 】 返回队列从start到end之间的元素信息。
7.【 ltrim key start end 】 截取一个队列,只保留指定区间内的元素。
list常见的操作:
(1)lpush和rpush
lpush表示在key对应的list的头部添加字符串元素。例如:lpush list Hello
rpush表示在key对应的list的尾部添加字符串元素。例如:rpush list World
(2)lpop和rpop
lpop代表从list的头部删除元素,并返回元素。
rpop代表从list的头部删除元素,并返回元素。
(3)lrange
取出指定范围内的元素。例如:lrange list 0 -1,0是第一个元素的下标,-1是最后一个元素的下标。
(4)linsert
在key对应的list的特定位置前或后添加字符串,例如:
linsert list before Hello Redis 表示在list链表的Hello前面插入一个元素Redis
(5)lset
设定list中指定下标的元素值,例如:lset list 1 Database,意思是把list中下标为1的元素替换为
Database。
(6)lrem
从key对应的list中删除n个和value相同的元素,如果n<0表示从尾部删除,n=0表示全部删除。
例如:lrem list 1 Hello
(7)ltrim
保留指定key范围内的数据。比如:ltrim list 1 -1,相当于只保留下表从1开始到最后的元素的值。
(8)rpoplpush
从第一个list的尾部移除元素并添加到第二个list的头部。例如:
(9)lindex
返回名称为key的list中index位置的元素。例如:lindex list 1,返回list中下标为1的元素。
(10)llen
返回key对应list的长度。
命令示例:
Redis关于list类型操作
1>栈的特性:先进后出,后进先出
2>队列的特性:先进先出,后进后出
List是一个链表结构,既可可以做为栈也可以作为队列处理数据.
lpush mylist "world" //向mylist尾部中放入world
lpush mylist "hello" //向mylist尾部中存入hello
lrange 0 -1 //获取mylist中的所有元素
rpush mylist2 "hello" //向mylist头部中存入hello
rpush mylist2 "world" //向mylist头部中存入world
lrange 0 -1
linsert mylist2 before world "xhy" //向mylist中world元素前插入"xhy"
lset mylist2 0 "example" //设置mylist中的第0个元素的值为"example"
lpush mylist_rem "one"
lpush mylist_rem "one"
lpush mylist_rem "one"
lrem mylist_rem 1 "one //删除1个值为"one"的元素
lpush mylist_ltrim "one"
lpush mylist_ltrim "two"
lpush mylist_ltrim "three"
lpush mylist_ltrim "four"
lpush mylist_ltrim "five"
ltrim mylist_ltrim 2 3 //除了第2和第3个元素,删除其它元素
lpush list_pop 1
lpush list_pop 1
lpush list_pop 1
lrange list_pop 0 -1
lpop list_pop //从头部删除list_pop的第一个元素
rpop list_pop //从尾部删除list_pop的第一个元素
lpush list_1 0
lpush list_1 1
lpush list_1 2
lpush list_1 3
lrange list_1 0 -1
lpush list_2 4
lpush list_2 5
lpush list_2 6
lpush list_2 7
lrange list_2 0 -1
rpoplpush list_1 list_2 //从list_1中的尾部弹出第1个元素并添加到list_2的头部中
lindex list_2 0 //取出list_2第0个元素
lindex list_2 1
llen //返回链表的长度
命令示例:
1. LPUSH/LPUSHX/LRANGE:
/> redis-cli#在Shell提示符下启动redis客户端工具。
redis 127.0.0.1:6379> del mykey
(integer) 1
#mykey键并不存在,该命令会创建该键及与其关联的List,之后在将参数中的values从左到右依次插入。
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
#取从位置0开始到位置2结束的3个元素。
redis 127.0.0.1:6379> lrange mykey 0 2
1) "d"
2) "c"
3) "b"
#取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
#mykey2键此时并不存在,因此该命令将不会进行任何操作,其返回值为0。
redis 127.0.0.1:6379> lpushx mykey2 e
(integer) 0
#可以看到mykey2没有关联任何List Value。
redis 127.0.0.1:6379> lrange mykey2 0 -1
(empty list or set)
#mykey键此时已经存在,所以该命令插入成功,并返回链表中当前元素的数量。
redis 127.0.0.1:6379> lpushx mykey e
(integer) 5
#获取该键的List Value的头部元素。
redis 127.0.0.1:6379> lrange mykey 0 0
1) "e"
2. LPOP/LLEN:
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
redis 127.0.0.1:6379> lpop mykey
"d"
redis 127.0.0.1:6379> lpop mykey
"c"
#在执行lpop命令两次后,链表头部的两个元素已经被弹出,此时链表中元素的数量是2
redis 127.0.0.1:6379> llen mykey
(integer) 2
3. LREM/LSET/LINDEX/LTRIM:
#为后面的示例准备测试数据。
redis 127.0.0.1:6379> lpush mykey a b c d a c
(integer) 6
#从头部(left)向尾部(right)变量链表,删除2个值等于a的元素,返回值为实际删除的数量。
redis 127.0.0.1:6379> lrem mykey 2 a
(integer) 2
#看出删除后链表中的全部元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "d"
3) "c"
4) "b"
#获取索引值为1(头部的第二个元素)的元素值。
redis 127.0.0.1:6379> lindex mykey 1
"d"
#将索引值为1(头部的第二个元素)的元素值设置为新值e。
redis 127.0.0.1:6379> lset mykey 1 e
OK
#查看是否设置成功。
redis 127.0.0.1:6379> lindex mykey 1
"e"
#索引值6超过了链表中元素的数量,该命令返回nil。
redis 127.0.0.1:6379> lindex mykey 6
(nil)
#设置的索引值6超过了链表中元素的数量,设置失败,该命令返回错误信息。
redis 127.0.0.1:6379> lset mykey 6 hh
(error) ERR index out of range
#仅保留索引值0到2之间的3个元素,注意第0个和第2个元素均被保留。
redis 127.0.0.1:6379> ltrim mykey 0 2
OK
#查看trim后的结果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "e"
3) "c"
4. LINSERT:
#删除该键便于后面的测试。
redis 127.0.0.1:6379> del mykey
(integer) 1
#为后面的示例准备测试数据。
redis 127.0.0.1:6379> lpush mykey a b c d e
(integer) 5
#在a的前面插入新元素a1。
redis 127.0.0.1:6379> linsert mykey before a a1
(integer) 6
#查看是否插入成功,从结果看已经插入。注意lindex的index值是0-based。
redis 127.0.0.1:6379> lindex mykey 0
"e"
#在e的后面插入新元素e2,从返回结果看已经插入成功。
redis 127.0.0.1:6379> linsert mykey after e e2
(integer) 7
#再次查看是否插入成功。
redis 127.0.0.1:6379> lindex mykey 1
"e2"
#在不存在的元素之前或之后插入新元素,该命令操作失败,并返回-1。
redis 127.0.0.1:6379> linsert mykey after k a
(integer) -1
#为不存在的Key插入新元素,该命令操作失败,返回0。
redis 127.0.0.1:6379> linsert mykey1 after a a2
(integer) 0
5. RPUSH/RPUSHX/RPOP/RPOPLPUSH:
#删除该键,以便于后面的测试。
redis 127.0.0.1:6379> del mykey
(integer) 1
#从链表的尾部插入参数中给出的values,插入顺序是从左到右依次插入。
redis 127.0.0.1:6379> rpush mykey a b c d
(integer) 4
#通过lrange的可以获悉rpush在插入多值时的插入顺序。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
#该键已经存在并且包含4个元素,rpushx命令将执行成功,并将元素e插入到链表的尾部。
redis 127.0.0.1:6379> rpushx mykey e
(integer) 5
#通过lindex命令可以看出之前的rpushx命令确实执行成功,因为索引值为4的元素已经是新元素了。
redis 127.0.0.1:6379> lindex mykey 4
"e"
#由于mykey2键并不存在,因此该命令不会插入数据,其返回值为0。
redis 127.0.0.1:6379> rpushx mykey2 e
(integer) 0
#在执行rpoplpush命令前,先看一下mykey中链表的元素有哪些,注意他们的位置关系。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
#将mykey的尾部元素e弹出,同时再插入到mykey2的头部(原子性的完成这两步操作)。
redis 127.0.0.1:6379> rpoplpush mykey mykey2
"e"
#通过lrange命令查看mykey在弹出尾部元素后的结果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
#通过lrange命令查看mykey2在插入元素后的结果。
redis 127.0.0.1:6379> lrange mykey2 0 -1
1) "e"
#将source和destination设为同一键,将mykey中的尾部元素移到其头部。
redis 127.0.0.1:6379> rpoplpush mykey mykey
"d"
#查看移动结果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "a"
3) "b"
4) "c"