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);
}
}
}


1025

被折叠的 条评论
为什么被折叠?



