4.3 list
4.3.1 概述
- 存储内容
可存储有序的字符串列表; - 常用操作
向列表两端添加元素、获取列表的某一个片段; - 底层实现
基于双向链表(double linked list); - 性能特性
- 向列表两端添加元素的时间复杂度为 O (1);
- 获取元素时,越接近列表两端的元素,访问速度越快;
- 极端场景验证:即便列表包含几千万个元素,获取其头部或尾部的 10 条记录仍能达到极快的速度。
4.3.2 命令
-
向列表两端增加元素
执行 lpush/rpush 时,Redis 会自动创建这个列表,并将元素插入。如果列表存在就会在已有列表上进行操作。
向列表(key)的左侧(头部) 增加一个 / 多个元素。
多个值按传入顺序依次从左侧插入。lpush key value [value ...]
向列表(key)的右侧(尾部) 增加一个 / 多个元素。
多个值按传入顺序依次从右侧插入。
rpush key value [value ...]

结果:3 → 2 → 1 → 4 → 5 → 6
-
从列表两端弹出元素
lpop key
rpop key
lpop命令从列表左边弹出一个元素,会分两步完成。第一步是将列表左边的元素从列表中移除,第二步是返回被移除的元素值。rpop同理。

-
获取列表中元素个数
llen key

4.获取列表片段
lrange key start stop
lrange命令是列表类型最常用的命令之一,获取列表中的某一片段,将返回start、stop之间的所有元素(包含两端的元素),索引从0开始。索引可以是负数,如:"-1"代表最后边的一个元素。

-
删除列表中指定的值
lrem key count value
lrem命令会在列表里找值为value的元素,然后只删除其中的的前count个。
根据count值的不同,该命令的执行方式会有所不同:
- 当count>0时, LREM会从列表左边开始删除。
- 当count<0时, LREM会从列表后边开始删除。
- 当count=0时, LREM删除所有值为value的元素。

-
获取/设置指定索引的元素值
LINDEX key index
LSET key index value

-
只保留列表指定片段
只保留列表指定片段,指定范围和LRANGE一致LTRIM key start stop

8.向列表中插入元素
LINSERT key BEFORE|AFTER pivot value
该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。

-
将元素从一个列表转移到另一个列表中
先从 source 列表的右侧(尾部) 弹出一个元素。
再把这个元素插入到 destination 列表的左侧(头部)。
返回被移动的元素。RPOPLPUSH source destination

4.3.3 方法
- List 类型核心操作
|------------|----------------------------------------|-------------|-------------------------------------------------------|
| 功能 | StringRedisTemplate 方法 | 对应 Redis 命令 | 代码中的作用 |
| 右侧(尾部)添加元素 | opsForList().rightPush(key, value) | rpush | 向列表尾部追加单个元素 |
| 左侧(头部)添加元素 | opsForList().leftPush(key, value) | lpush | 向列表头部插入单个元素(最新元素在头部,适合评论 / 消息场景) |
| 获取指定范围元素 | opsForList().range(key, start, end) | lrange | 获取列表中 start 到 end 下标元素( 0,-1 表示所有元素, 0,3 表示前 4 个) |
| 获取列表长度 | opsForList().size(key) | llen | 返回列表的元素总个数 |
| 修改指定下标值 | opsForList().set(key, index, value) | lset | 更新列表中指定下标位置的元素值 |
| 获取指定下标值 | opsForList().index(key, index) | lindex | 查询列表中指定下标位置的元素值 |
| 删除指定数量的目标值 | opsForList().remove(key, count, value) | lrem | 按方向删除 count 个值为 value 的元素( count>0 从左删, count=0 删所有) |
| 截取列表保留指定区间 | opsForList().trim(key, start, end) | ltrim | 仅保留列表中 start 到 end 下标元素,删除区间外所有元素 |
| 左侧(头部)出栈 | opsForList().leftPop(key) | lpop | 从列表头部弹出元素(元素从列表中移除,返回弹出值) |
- List 关联的通用操作
|---------|--------------------------------------------------|-------------|--------------------------------------------|
| 功能 | StringRedisTemplate 方法 | 对应 Redis 命令 | 代码中的作用 |
| 删除整个列表 | delete(key) | del | 直接删除列表键,清空列表所有元素 |
| 清空当前数据库 | getConnectionFactory().getConnection().flushDb() | flushdb | 清空当前 Redis 库的所有键(含 List、Hash、String 等所有类型) |
- 结论
- List 类型操作的核心套路:stringRedisTemplate.opsForList().xxx();
- 方向相关:rightPush/leftPush 对应 "尾加 / 头加",leftPop 对应 "头出",符合 Redis List 双向链表特性;
- 范围操作:range/trim 的下标规则和 Redis 一致(从 0 开始,-1 表示最后一个元素);
- 删除逻辑:remove 仅删除 "值匹配" 的元素,count 控制删除数量和方向,而非删除列表下标元素。
-
代码
package com.qcby.springbootredis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.List;
@SpringBootTest
public class ListTest {
// 注入 SpringBoot 自带的 StringRedisTemplate(替代 Jedis,自动管理连接池)
@Autowired
private StringRedisTemplate stringRedisTemplate;/**
-
List 类型核心操作(对应原 Jedis 的 testList 方法)
*/
@Test
public void testList() {
System.out.println("==List==");
try {
// ========== 1. 移除指定 list 的所有内容==========
stringRedisTemplate.delete("messages");// ========== 2. 向 list 右侧(尾部)添加元素 ========== stringRedisTemplate.opsForList().rightPush("messages", "Hello how are you?"); stringRedisTemplate.opsForList().rightPush("messages", "Fine thanks. I'm having fun with redis."); stringRedisTemplate.opsForList().rightPush("messages", "I should look into this NOSQL thing ASAP"); // ========== 3. 获取 list 所有元素 ========== // 0 = 起始下标,-1 = 结束下标(表示所有元素) List<String> values = stringRedisTemplate.opsForList().range("messages", 0, -1); System.out.println("messages 所有元素:" + values); // ========== 4. 清空当前数据库 ========== stringRedisTemplate.getConnectionFactory().getConnection().flushDb(); System.out.println("清空当前数据库成功"); // ========== 5. 向 list 左侧(头部)添加元素 ========== stringRedisTemplate.opsForList().leftPush("lists", "vector"); stringRedisTemplate.opsForList().leftPush("lists", "ArrayList"); stringRedisTemplate.opsForList().leftPush("lists", "LinkedList"); // ========== 6. 获取 list 长度 ========== Long listSize = stringRedisTemplate.opsForList().size("lists"); System.out.println("lists 长度:" + listSize); // ========== 7. 获取 list 指定范围元素 ========== List<String> rangeValues = stringRedisTemplate.opsForList().range("lists", 0, 2); System.out.println("lists 0-2 范围元素:" + rangeValues); // ========== 8. 修改 list 指定下标的值 ========== stringRedisTemplate.opsForList().set("lists", 0, "hello list!"); System.out.println("修改 lists 下标 0 的值为 hello list! 成功"); // ========== 9. 获取 list 指定下标的值(对应 jedis.lindex("lists", 1)) ========== String indexValue = stringRedisTemplate.opsForList().index("lists", 1); System.out.println("lists 下标 1 的值:" + indexValue); // ========== 10. 删除 list 中指定数量的目标值 ========== // 参数:key、删除数量(count)、目标值(value)→ 从左删 1 个 "vector" Long removeCount = stringRedisTemplate.opsForList().remove("lists", 1, "vector"); System.out.println("删除 lists 中 vector 的数量:" + removeCount); // ========== 11. 截取 list 保留指定区间,删除区间以外的数据 ========== stringRedisTemplate.opsForList().trim("lists", 0, 1); System.out.println("截取 lists 0-1 区间,删除其他元素成功"); // ========== 12. list 左侧(头部)出栈 ========== String leftPopValue = stringRedisTemplate.opsForList().leftPop("lists"); System.out.println("lists 左侧出栈元素:" + leftPopValue); // ========== 13. 再次获取 list 所有元素,查看最终结果 ========== List<String> finalValues = stringRedisTemplate.opsForList().range("lists", 0, -1); System.out.println("lists 最终剩余元素:" + finalValues);} catch (Exception e) {
e.printStackTrace();
}
}
/**
-
商品评论列表业务场景实现
*/
@Test
public void testGoodsCommentList() {
// 1. 定义商品评论列表 key(商品 1001 的评论)
String goodsCommentKey = "items:comment:1001";// 2. 模拟用户发布商品评论(将评论转为 JSON 字符串,左侧插入List → 最新评论在头部)
String comment1 = "{"id":1,"name":"商品不错,很好!!","date":1430295077289}";
String comment2 = "{"id":2,"name":"质量很好,性价比高","date":1430295177289}";
stringRedisTemplate.opsForList().leftPush(goodsCommentKey, comment1);
stringRedisTemplate.opsForList().leftPush(goodsCommentKey, comment2);// 3. 模拟页面查询评论列表(从 Redis 中取出所有评论 JSON 数据)
List<String> goodsComments = stringRedisTemplate.opsForList().range(goodsCommentKey, 0, -1);// 4. 打印展示评论列表(实际开发中可反序列化为对象,返回给前端页面)
System.out.println("商品 1001 评论列表:");
for (String comment : goodsComments) {
System.out.println(comment);
}
}
}
-

