Redis的List数据结构操作

111 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

Redis中的list和Java中的LinkedList很像,底层都是一种链表结构, list的插入和删除操作非常快,时间复杂度为 0(1),不像数组结构插入、删除操作需要移动数据。

像归像,但是redis中的list底层可不是一个双向链表那么简单。

当数据量较少的时候它的底层存储结构为一块连续内存,称之为ziplist(压缩列表),它将所有的元素紧挨着一起存储,分配的是一块连续的内存;当数据量较多的时候将会变成quicklist(快速链表)结构。

可单纯的链表也是有缺陷的,链表的前后指针 prev 和 next 会占用较多的内存,会比较浪费空间,而且会加重内存的碎片化。在redis 3.2之后就都改用ziplist+链表的混合结构,称之为 quicklist(快速链表)。

应用场景:

消息队列:lpop和rpush(或者反过来,lpush和rpop)能实现队列的功能

朋友圈的点赞列表、评论列表、排行榜:lpush命令和lrange命令能实现最新列表的功能,每次通过lpush命令往列表里插入新的元素,然后通过lrange命令读取最新的元素列表。

初始化数据:
ListOperations listOperations = redisTemplate.opsForList();
//在变量左边添加元素值。
listOperations.leftPush("listtttt", "a");
listOperations.leftPush("listtttt", "b");
listOperations.leftPush("listtttt", "c");
listOperations.leftPush("listtttt", "d");
listOperations.leftPush("listtttt", "e");
常见操作:

//在变量左边添加元素值。

  • listOperations.leftPush(key, value);

//向左边批量添加参数元素。

  • Long leftPushAll(K key, V... values);
listOperations.leftPushAll("listtttt", "f","g");

//以集合的方式向左边批量添加元素。

  • Long leftPushAll(K key, Collection values);
listOperations.leftPushAll("listtttt", Lists.newArrayList("h","k"));

//向右边添加元素

  • Long rightPush(K key, V value);

//向右边批量添加元素。

  • Long rightPushAll(K key, V... values);
  • Long rightPushAll(K key, Collection values);
listOperations.rightPushAll("listtttt", "x","y","z");
System.out.println("listtttt init:"+listOperations.range("listtttt",0,-1));

//获取指定区间的值。[0,-1]表示所有的值

  • List range(K key, long start, long end);
List<Character> characters = listOperations.range("listtttt", 0, 5);
System.out.println("List<Character> characters:"+characters);

//获取集合长度。

  • Long size(K key);
Long size = listOperations.size("listtttt");
System.out.println("element size = "+size);

//从左边移除一个元素

  • V leftPop(K key);
  • List leftPop(K key, long count);
Object lpop = listOperations.leftPop("listtttt");
System.out.println(lpop);

//移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。

  • V leftPop(K key, long timeout, TimeUnit unit);
listOperations.leftPop("testtt", 2, TimeUnit.SECONDS);
System.out.println(listOperations.range("listtttt", 0, -1));

//从右边移除一个元素;在等待的时间里,如果超过等待的时间仍没有元素则退出。

  • V rightPop(K key);
  • List rightPop(K key, long count);
  • V rightPop(K key, long timeout, TimeUnit unit);
Object rpop = listOperations.rightPop("listtttt");
System.out.println(rpop);
System.out.println(listOperations.range("listtttt", 0, -1));

//获取指定位置的值,获取指定值的下标

  • V index(K key, long index);
  • Long indexOf(K key, V value);
  • Long lastIndexOf(K key, V value);
Object eight = listOperations.index("listtttt", 8);
System.out.println("下标为8的元素是"+eight);

//已存在集合最左边添加元素

  • Long leftPushIfPresent(K key, V value);
listOperations.leftPushIfPresent("listtttt","b");

//已存在的集合向最右边添加元素

  • Long rightPushIfPresent(K key, V value);
listOperations.rightPushIfPresent("listtttt","b");

//移除列表的最后一个元素,并将该元素添加到另一个列表并返回

  • V rightPopAndLeftPush(K sourceKey, K destinationKey);

//listOperations.rightPopAndLeftPush(sourceKey, destinationKey);

listOperations.rightPopAndLeftPush("listtttt", "listttttDes");

//从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

  • V rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit);
  • default V rightPopAndLeftPush(K sourceKey, K destinationKey, Duration timeout);
listOperations.rightPopAndLeftPush("listtttt", "listttttDes",2, java.util.concurrent.TimeUnit.SECONDS);

//在集合的指定位置插入元素,如果指定位置已有元素,则覆盖,没有则新增,超过集合下标+n则会报错。

  • void set(K key, long index, V value);
listOperations.set("listttttDes",1, "o");

//从存储在键中的列表中删除等于值的元素的第一个计数事件。count> 0:删除等于从左到右移动的值的第一个元素;count< 0:删除等于从右到左移动的值的第一个元素;count = 0:删除等于value的所有元素。

  • Long remove(K key, long count, Object value);
Long rem = listOperations.remove("listttttDes", 0,"o");
System.out.println(rem+"  listttttDes="+listOperations.range("listttttDes",0,-1));

// 删除先进入的B元素(如果含有多个B元素,删除最左边的)
Long stringRedisTemplate.opsForList().remove("redlist",1, "B");
//["0","1","2","A"]

// 删除最右边A元素
Long stringRedisTemplate.opsForList().remove("redlist",-1, "A");
//["0","1","2"]

//截取集合元素长度,保留长度内的数据。

  • void trim(K key, long start, long end);
listOperations.trim("listOperations", 0,5);
System.out.println(listOperations.range("listOperations", 0, -1));