当前位置: 首页 > news >正文

实战讲解Redis基础数据类型List增删改查(带Java源码)

1 缘起

继续补充基础数据类型List操作,
帮助读者系统学习List相关知识。

注意:

(1)文末附全部测试代码;
(2)本篇文章将学习使用如下函数(方法):

序号操作method
1新增lpush,rpush,linsert
2删除lpop,rpop,brpoplpush,ltrim
3修改lset
4查询llen,lrange,lindex,lpos

2 List测试

Redis基础数据类型List代表存储的值(value)为列表。
本文采用连接池的方式直连Redis,连接池配置如下:

  • 依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.1</version>
</dependency>
  • Redis连接池配置(可以根据需要设置为共用)
private static JedisPool getJedisPool() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // Jedis池:最大连接数
        jedisPoolConfig.setMaxTotal(1);
        // Jedis池:最大空闲连接数
        jedisPoolConfig.setMaxIdle(10);
        // Jedis池:等待时间
        jedisPoolConfig.setMaxWaitMillis(3000);
        // Jedis池:连接Redis超时时间
        int connectTimeout = 2000;
        String redisHost = "127.0.0.1";
        int redisPort = 6379;
        String redisPassword = "123456";
        int redisDb = 0;
        // 创建连接池
        return new JedisPool(jedisPoolConfig, redisHost, redisPort, connectTimeout, redisPassword, redisDb);
    }

2.1 新增数据

List新增数据有三种情况,
Redis的列表类型数据按照左右两侧插入,
同时,支持在指定元素的前或者后面插入数据,
测试样例如下:

    /**
     * 新增数据.
     * lpush:从头部新增:左侧进入列表
     * rpush:从尾部新增:右侧进入列表
     * linsert:指定数据前/后添加数据
     */
    @Test
    public void insertData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 从队列头部入队
            Long res1 = jedis.lpush("namelist", "xiaoyi", "xiaoer", "xiaosan");
            // 从队列尾部入队
            Long res2 = jedis.rpush("namelist", "xiaosi", "xiaowu", "xiaoliu");
            // 在给定数据后面插入数据
            Long res3 = jedis.linsert("namelist", ListPosition.AFTER, "xiaoliu", "xiaox");
            // 在给定数据前面插入数据
            Long res4 = jedis.linsert("namelist", ListPosition.BEFORE, "xiaoliu", "xiaox");
            logger.info(">>>>>>>List插入数据:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis插入List数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

2.1.1 lpush

左侧插入数据源码如下图所示,
由注释可知,向list添加字符串数据,如果列表中键不存在则新建数据,如果键存在,但是,不是在list中,则返回错误。
时间复杂度:O(1)
在这里插入图片描述

2.1.2 rpush

list从右侧插入数据,其他同lrpush。
在这里插入图片描述

2.1.3 linsert

这个方法没有注释,不过,从使用结果来看,
是在某个元素的前面或后面插入数据。
在这里插入图片描述

2.2 删除数据

List插入数据分左、右,
删除数据同样有左右之分,
同时,支持两个列表相互操作(brpoplpush)以及截取指定范围的数据,
测试样例如下:

    /**
     * 删除数据.
     * lpop: 从,头部开始删除(列表左侧)
     * rpop: 从,尾部开始删除(列表右侧)
     * brpoplpush: 先删除列表A的数据,然后插入列表B,并返回删除的数据
     * ltrim: 截取给定范围内的数据,删除范围外的数据
     */
    @Test
    public void deleteData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 从队列头部移除元素
            String res1 = jedis.lpop("namelist");
            // 从队列尾部移除元素
            String res2 = jedis.rpop("namelist");
            // 从namelist-1尾部删除数据并将该数据添加到namelist-2头部,返回该数据
            String res3 = jedis.brpoplpush("namelist-1", "namelist-2", 10);
            // 截取数据,保留指定区间的数据,保留0~5条数据
            String res4 = jedis.ltrim("namelist", 0, 5);
            logger.info(">>>>>>>List删除数据:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis list删除数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

2.2.1 lpop

从左侧删除元素,
由注释可知,该方法为原子性方法。
在这里插入图片描述

2.2.2 rpop

从右侧删除数据,其他同lpop。
在这里插入图片描述

2.2.3 brpoplpush

这个方法比较有意思,
从列表a移除元素,然后存入列表b,
两个操作,放在一个方法中。
在这里插入图片描述

2.2.4 ltrim

之前的列表移除元素方法都是移除某一个元素,
当然,redis提供了批量操作,按照元素范围截取元素。
在这里插入图片描述

2.3 修改数据

Redis修改数据,
测试样例如下:

    /**
     * 编辑数据.
     * lset: 修改指定位置(索引)的数据
     */
    @Test
    public void editData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 修改指定位置数据
            String res1 = jedis.lset("namelist", 0, "xiaoling");
            logger.info(">>>>>>>List修改:{}", res1);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis修改数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

2.3.1 lset

修改数据源码如下所示,
由注释可知,在List指定位置使用新值覆盖旧值,
时间复杂度:O(n)。
在这里插入图片描述

2.4 查询数据

查询数据有四种方式:查询数据个数、查询指定索引范围数据、查询某个索引位置的数据以及查询指定元素的索引。
测试样例如下:

    /**
     * 查询数据.
     * llen: 查询列表存储数据个数
     * lrange: 查询给定范围内(索引)的数据
     * lindex: 查询指定位置(索引)的数据
     * lpos: 查询指定元素的索引,取遇到的第一个元素索引
     */
    @Test
    public void queryData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 查询List元素个数
            Long res1 = jedis.llen("namelist");
            // 查询范围内数据
            List<String> res2 = jedis.lrange("namelist", 0, 2);
            // 查询指定位置数据
            String res3 = jedis.lindex("namelist", 0);
            // 查询元素所在位置,取遇到的第一个元素索引
            Long res4 = jedis.lpos("namelist", "xiaoling");
            logger.info(">>>>>>>List查询:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis list查询数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

2.4.1 llen

查询List长度源码如下图所示,
由注释可知,当列表为空或列表不存在返回0。
在这里插入图片描述

2.4.2 lrange

查询列表指定索引范围的元素源码如下图所示,
由注释可知,索引从0开始,查询给定范围的元素,返回列表。
在这里插入图片描述

2.4.3 lindex

查询某个索引的元素源码如下图所示,
由源码可知,索引0表示第一个元素,正数依次类推,
负数,-1表示最后一个元素,依次倒序类推。
在这里插入图片描述

2.4.4 lpos

查询某个元素的索引,源码如下图所示,
这个方法没有注释,按照测试的功能可知,
是获取某个元素的索引。
在这里插入图片描述

3 小结

Redis列表操作总结:

序号操作method
1新增lpush,rpush,linsert
2删除lpop,rpop,brpoplpush,ltrim
3修改lset
4查询llen,lrange,lindex,lpos

附件

package database_test.redis_test;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.ListPosition;

import java.util.List;

/**
 * List测试.
 *
 * @author xindaqi
 * @since 2022-08-16 9:43
 */
public class ListTest {

    private static final Logger logger = LoggerFactory.getLogger(ListTest.class);

    private static JedisPool getJedisPool() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // Jedis池:最大连接数
        jedisPoolConfig.setMaxTotal(1);
        // Jedis池:最大空闲连接数
        jedisPoolConfig.setMaxIdle(10);
        // Jedis池:等待时间
        jedisPoolConfig.setMaxWaitMillis(3000);
        // Jedis池:连接Redis超时时间
        int connectTimeout = 2000;
        String redisHost = "127.0.0.1";
        int redisPort = 6379;
        String redisPassword = "123456";
        int redisDb = 0;
        // 创建连接池
        return new JedisPool(jedisPoolConfig, redisHost, redisPort, connectTimeout, redisPassword, redisDb);
    }

    /**
     * 新增数据.
     * lpush:从头部新增:左侧进入列表
     * rpush:从尾部新增:右侧进入列表
     * linsert:指定数据前/后添加数据
     */
    @Test
    public void insertData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 从队列头部入队
            Long res1 = jedis.lpush("namelist", "xiaoyi", "xiaoer", "xiaosan");
            // 从队列尾部入队
            Long res2 = jedis.rpush("namelist", "xiaosi", "xiaowu", "xiaoliu");
            // 在给定数据后面插入数据
            Long res3 = jedis.linsert("namelist", ListPosition.AFTER, "xiaoliu", "xiaox");
            // 在给定数据前面插入数据
            Long res4 = jedis.linsert("namelist", ListPosition.BEFORE, "xiaoliu", "xiaox");
            logger.info(">>>>>>>List插入数据:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis插入List数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

    /**
     * 删除数据.
     * lpop: 从,头部开始删除(列表左侧)
     * rpop: 从,尾部开始删除(列表右侧)
     * brpoplpush: 先删除列表A的数据,然后插入列表B,并返回删除的数据
     * ltrim: 截取给定范围内的数据,删除范围外的数据
     */
    @Test
    public void deleteData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 从队列头部移除元素
            String res1 = jedis.lpop("namelist");
            // 从队列尾部移除元素
            String res2 = jedis.rpop("namelist");
            // 从namelist-1尾部删除数据并将该数据添加到namelist-2头部,返回该数据
            String res3 = jedis.brpoplpush("namelist-1", "namelist-2", 10);
            // 截取数据,保留指定区间的数据,保留0~5条数据
            String res4 = jedis.ltrim("namelist", 0, 5);
            logger.info(">>>>>>>List删除数据:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis list删除数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }

    /**
     * 编辑数据.
     * lset: 修改指定位置(索引)的数据
     */
    @Test
    public void editData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 修改指定位置数据
            String res1 = jedis.lset("namelist", 0, "xiaoling");
            logger.info(">>>>>>>List修改:{}", res1);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis修改数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }


    /**
     * 查询数据.
     * llen: 查询列表存储数据个数
     * lrange: 查询给定范围内(索引)的数据
     * lindex: 查询指定位置(索引)的数据
     * lpos: 查询指定元素的索引,取遇到的第一个元素索引
     */
    @Test
    public void queryData() {
        try (Jedis jedis = getJedisPool().getResource()) {
            // 查询List元素个数
            Long res1 = jedis.llen("namelist");
            // 查询范围内数据
            List<String> res2 = jedis.lrange("namelist", 0, 2);
            // 查询指定位置数据
            String res3 = jedis.lindex("namelist", 0);
            // 查询元素所在位置,取遇到的第一个元素索引
            Long res4 = jedis.lpos("namelist", "xiaoling");
            logger.info(">>>>>>>List查询:{}, {}, {}, {}", res1, res2, res3, res4);
        } catch (Exception ex) {
            logger.error(">>>>>>>>Redis list查询数据异常:", ex);
            throw new RuntimeException(ex);
        }
    }
}

相关文章:

  • 分布式消息队列RocketMQ介绍
  • Django视图层模版层全面解析全网最细的教程
  • java Map集合基本概念
  • 类与对象以及原型机制
  • IMX6ULL学习笔记(6)——通过USB OTG烧录U-Boot(MfgTool工具)
  • 牛客 NC25005 [USACO 2008 Ope S]Clear And Present Danger
  • 洛谷 P2349:金字塔 ← 链式前向星 dfs
  • Flink—窗口、时间和水印
  • Cadence OrCAD Capture 查找功能详细介绍
  • 物联网病毒Mirai可靠性分析
  • c语言实现数据结构中的单向链表
  • (没学懂,待填坑)【动态规划】数位动态规划
  • 小功能⭐️Unity判断是否单击到了UI
  • 常见的传输介质及其特性
  • 660——第一章
  • 《剑指offer》分解让复杂问题更简单
  • canvas 五子棋游戏
  • eclipse的离线汉化
  • java8-模拟hadoop
  • JS变量作用域
  • k8s如何管理Pod
  • Laravel 中的一个后期静态绑定
  • Lsb图片隐写
  • MySQL-事务管理(基础)
  • PaddlePaddle-GitHub的正确打开姿势
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • springMvc学习笔记(2)
  • swift基础之_对象 实例方法 对象方法。
  • vagrant 添加本地 box 安装 laravel homestead
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 阿里云前端周刊 - 第 26 期
  • 关于使用markdown的方法(引自CSDN教程)
  • 力扣(LeetCode)965
  • 项目实战-Api的解决方案
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • Nginx实现动静分离
  • 组复制官方翻译九、Group Replication Technical Details
  • (175)FPGA门控时钟技术
  • (rabbitmq的高级特性)消息可靠性
  • (二)springcloud实战之config配置中心
  • (二)正点原子I.MX6ULL u-boot移植
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net快速开发框架源码分享
  • .NET企业级应用架构设计系列之应用服务器
  • .net下的富文本编辑器FCKeditor的配置方法
  • .project文件
  • @property python知乎_Python3基础之:property
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [20170705]diff比较执行结果的内容.txt