在项目开发中,对列表的操作尤为重要,所以将列表相关的操作进行了简单的整理。
参考SpringDataRedis官方文档
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/ListOperations.html
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testRedisList() {
ListOperations<String, Object> listOperations = redisTemplate.opsForList();
// 1 添加值
// 1.1 向前添加
listOperations.leftPush("testList", "小明"); // 添加到最左侧
listOperations.leftPush("testList", "小红");
listOperations.leftPush("testList", "小明", "小黄"); // 在指定的元素(小明)前插入一个元素(小黄)
List<String> listData = new ArrayList<>();
listData.add("小黑");
listData.add("小白");
listOperations.leftPushAll("testList", listData); // 会将整个listData最为一个参数添加到最左侧 [[小黑, 小白], 小红, 小黄, 小明]
listOperations.leftPushAll("testList", "小紫", "小橙"); // 会将这两个,逐一添加到最左侧[小橙, 小紫, [小黑, 小白], 小红, 小黄, 小明]
listOperations.leftPushIfPresent("testList", "小蓝"); // 如果存在,则添加,否则不做操作 [小蓝, 小橙, 小紫, [小黑, 小白], 小红, 小黄, 小明]
listOperations.leftPushIfPresent("testList1", "小绿"); // testList1 不存在,则不做操作
// 1.2 向后添加,与向前添加,一模一样
listOperations.rightPush("testList", "大明");
listOperations.rightPush("testList", "大红");
listOperations.rightPush("testList", "大明", "大黄");
List<String> listData2 = new ArrayList<>();
listData2.add("大黑");
listData2.add("大白");
listOperations.rightPushAll("testList", listData2);
listOperations.rightPushAll("testList", "大紫", "大橙");
listOperations.rightPushIfPresent("testList", "大蓝");
// 查看结果
List<Object> testList = listOperations.range("testList", 0, -1);
log.info("testList: {}", testList);
log.info("testList2: {}", listOperations.range("testList2", 0, -1));
// 2 删除值
// 2.1 删除最左侧/右侧值
String LeftFirst = (String) listOperations.leftPop("testList"); // 删除,并返回前面第一个
List<Object> leftFirstList = listOperations.range("testList", 0, 1); // 从前开始,返回第start个到第end个,不删除
log.info("leftFirst: {}, leftFirstList: {}", LeftFirst, leftFirstList);
listOperations.leftPushAll("testList2", "大黄","大红");
listOperations.leftPop("testList2"); // 在testList2中添加,然后删除,只为创建一个空的队列
Duration timeout = Duration.ofSeconds(2);
String left2FirstTime = (String) listOperations.leftPop("testList2", timeout); // 删除最左侧,并设置超时时间。如果10秒之内,没有数据,则返回null,如果有数据,则直接删除并返回数据
log.info("left2FirstTime: {}", left2FirstTime);
String left2FirstTime2 = (String) listOperations.leftPop("testList2", 3, TimeUnit.SECONDS); // 与上面一模一样,只不过表示时间的方法不同,更推荐上面的写法
log.info("left2FirstTime2: {}", left2FirstTime2);
String RightFirst = (String) listOperations.rightPop("testList");
List<Object> rightFirstList = listOperations.range("testList", 0, 1);
String RightFirstTime = (String) listOperations.rightPop("testList", timeout);
log.info("RightFirst: {}, rightFirstList: {}, RightFirstTime: {}", RightFirst, rightFirstList, RightFirstTime);
// 2.2 删除指定数量的值
listOperations.leftPushAll("testList", "大黄", "大黄", "大黄");
listOperations.remove("testList", 4, "大黄"); // 删除指定数量的指定的值,从前向后:删除4个大黄 如果找不到,则不做操作
// 2.3 保留指定区间的值,其余都删除
listOperations.trim("testList", 2, 7); // 删除指定区间的值,从0开始,到2结束,包含2和7
// 3 修改
listOperations.set("testList", 0, "color"); // 修改指定位置的值
// 查看 添加、删除和修改之后的结果
List<Object> testListDel = listOperations.range("testList", 0, -1);
log.info("testList: {}", testListDel);
// 4 查看
// 4.1 查看列表的长度
Long size = listOperations.size("testList");
log.info("size: {}", size);
// 4.2 查看开头或结尾的值
String firstValue = (String) listOperations.index("testList", 0); // 在官方文档中是有 getFirst(K key) 这个属性的,但是在这个版本中,没有这个属性,所以用 index String lastValue = (String) listOperations.index("testList", -1); // 在官方文档中是有 getLast(K key) 这个属性的,但是在这个版本中,没有这个属性,所以用 index log.info("firstValue: {}, lastValue: {}", firstValue, lastValue);
// 4.3 查看指定位置的值
String keyValue = (String) listOperations.index("testList", 3);
log.info("keyValue: {}", keyValue);
// 4.4 查看所有的值
List<Object> allValue = listOperations.range("testList", 0, -1);
log.info("allValue: {}", allValue);
// 4.5 查看列表中第一次和最后一次出现的索引位置
Long firstIndex = listOperations.indexOf("testList", "小红");
Long lastIndex = listOperations.lastIndexOf("testList", "大明");
log.info("firstIndex: {}, lastIndex: {}", firstIndex, lastIndex);
// 5 移动
// 5.1 将前置列表中的最后一个值移动到后者列表的第一个值
String rightPotAndLeftPot = (String) listOperations.rightPopAndLeftPush("testList", "testList2");
String rightPotAndLeftPotTime = (String) listOperations.rightPopAndLeftPush("testList2", "testList", timeout);
String rightPotAndLeftPotTime2 = (String) listOperations.rightPopAndLeftPush("testList2", "testList", 3, TimeUnit.SECONDS);
log.info("rightPotAndLeftPot: {}, rightPotAndLeftPotTime: {}, rightPotAndLeftPotTime2: {}", rightPotAndLeftPot, rightPotAndLeftPotTime, rightPotAndLeftPotTime2);
// 5.2 更加灵活的移动
listOperations.move(ListOperations.MoveFrom.fromTail("testList"), ListOperations.MoveTo.toHead("testList")); // 最基本的版本,从任意列表的尾部移动到任意列表的头部
listOperations.move(ListOperations.MoveFrom.fromHead("testList"), ListOperations.MoveTo.toHead("testList2"), timeout); // 带超时的版本
listOperations.move("testList", RedisListCommands.Direction.first(), "testList2", RedisListCommands.Direction.last()); // 与抵押给案例中一样,只是参数不同,但更推荐使用前者
listOperations.move("testList", RedisListCommands.Direction.first(), "testList2", RedisListCommands.Direction.last(), 3, TimeUnit.SECONDS);
listOperations.move("testList", RedisListCommands.Direction.last(), "testList2", RedisListCommands.Direction.first(), timeout); // 这两个与第二个相同,同样更推荐使用第二个
log.info("list:{}", listOperations.range("testList", 0, -1));
log.info("list2:{}", listOperations.range("testList2", 0, -1));
}