Redis的列表类型可以跟编程语言中的列表对应,如果要与Java对应的话,可以认为Redis的列表相当于Java中的Stack吧,但在实现上可以认为相当于Java的LinkedList,但Redis的这个LinkedList是双向的,下面看看Redis关于List的操作吧!
1、设值/取值
由于List相当于一个双向的LinkedList,所以可以往这个链表的两端都插入数据,分别提供了LPUSH和RPUSH来操作设值。Redis命令的一大优点就是见名知意。LPUSH:Left Push, RPUSH: Right Push.而提供了LPOP和RPOP来取值。看下边的演示吧!
其中LLEN表示获取这个列表的值的个数,LPUSH返回的是操作成功后列表中元素的个数。
前面说了List内部是使用双向链表实现的,所以有LPUSH、RPUSH和LPOP、RPOP指令来操作,但为什么又说可以认为List是java中的Stack呢?
①、操作指令的名称,与java中Stack的方法名称一致
②、执行lpop操作, 最左边的元素就移除了,跟Stack的操作一致。
2、获取List元素个数
使用LLEN可以获取指定列表的元素个数,如果Key对应的List不存在,则返回0,如果List长度为0,也会返回0.所以在重申一遍,判断Key是否存在只有EXISTS指令,其他指令,比如LLEN,都不能肯定判断Key是否存在。当然LLEN命令也只能用于List类型。
3、截取列表片段
使用LRANGE指令来截取列表片段,使用示例如下:
从以上示例可以得出两点,1)、List的索引是从0开始的。2)、List的LRANGE的范围是包含关系[]而不是()。
LRANGE还支持负索引,从右边第一个元素起,-1代表最右边第一个元素,-2代表第二个,依次类推。
所以LRANGE list 0 -1就是截取整个列表,与LPOP,RPOP不同的是,LRANGE并不会改变原List的元素。
如果索引end大于列表的最大索引,则end就为最大索引,如果start大于最大索引,返回的是一个空列表。如果start > end返回空列表。
4、删除列表中的元素
使用LREM指令删除元素,格式为 LREM list count value,这个指令采取的行动取决于count的值。返回值为删除元素的个数。
count > 0, 则从左边开始删除前count个值为value的元素
count < 0, 则从右边开始删除前-count个值为value的元素
count = 0, 则删除所有值为value的元素
演示如下:
5、获得/设置指定索引位置的值
如果你会java语言,那么你对ArrayList的get和indexOf方法等一定不陌生,Redis也提供了这个操作。
LINDEX获取指定索引位置的值,格式 LINDEX list index, LINDEX与前面的LRANGE一样,支持负索引。
LSET也是支持负索引的。
6、保留指定片段
LTRIM会保留指定片段,而在范围外的片段会丢弃掉,格式LTRIM list start end。
其实这个命令与LRANGE命令很类似,不同之处就是会将范围外的元素丢弃掉。同样支持负索引。
7、插入元素
如果有多个值,则选第一个,如果没找到,不会进行插入,会返回-1.使用如下:
8、将列表A中的元素转移到列表B中去
RPOPLPUSH指令,格式RPOPLPUSH source des。这个指令非常容易理解,使用RPOP弹出source中的一个元素,然后使用LPUSH将其放入des中。
Redis List的java使用
测试代码如下:
package org.yamikaze.redis.test;
import redis.clients.jedis.Jedis;
import java.util.List;
/**
* 测试Redis的List类型
* @author yamikaze
*/
public class TestList {
public static void main(String[] args) {
Jedis client = MyJedisFactory.defaultJedis();
String key = "list1";
String value1 = "1";
String value2 = "2";
String value3 = "3";
String value4 = "4";
/**
* 对应LPUSH
*/
Long listLength = client.lpush(key, value1, value2, value3, value4);
/**
* 对应LLEN
*/
Long length = client.llen(key);
System.out.println(length.equals(listLength));
/**
* 对应LPOP
*/
String value = client.lpop(key);
System.out.println(value4.equals(value));
/**
* 对应LREM
*/
Long remSize = client.lrem(key, 1, "1");
//前面pop了一个元素,这儿删除了一个元素 所以-2
System.out.println((length - remSize - 1) == (length -2));
/**
* 对应LRANGE
*/
List<String> valueList = client.lrange(key, 0, -1);
System.out.println((length - 2) == valueList.size());
/**
* 其他List的指令都能在Jedis的API中找到,限于篇幅原因就不一一演示了。
*/
}
}
总结
Redis的List内部是使用双向链表设计的,所以往List两端插入元素速度是很快的,但使用链表,就意味着遍历速度会很慢(这是链表结构的通病),所以用到索引的指令建议不要经常使用,因为链表很长的话会很耗时。
参考书籍
《Redis入门指南》