码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • redis使用rightPushAll保存List,List的size为1


    redis使用rightPushAll保存List,List的size为1

    • 问题描述
    • 问题定位
    • 解决方案:
    • 问题疑惑

    问题描述

    使用RedisTemplate保存List,期望是直接将Java的List直接转换redis的list。但是rightPushAll执行之后,却将整个list作为一个元素存到redis里面了。代码demo如下

    @Controller
    public class RedisTest {
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        @ResponseBody
        @GetMapping("/test")
        public Long test(){
         	String key = "test";
            redisTemplate.delete(key);
            ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add("1");
            arrayList.add("2");
            arrayList.add("3");
            Long size = redisTemplate.opsForList().rightPushAll(key, arrayList); 
            //output 1
            System.out.println(redisTemplate.opsForList().size(key));
            List<Object> range = redisTemplate.opsForList().range(key, 0, -1);
            //output [[1, 2, 3]]
            System.out.println(range);
            return size;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    执行想要的结果是size=3,list=[1, 2, 3]。但是执行的结果却是size=1,list=[[1, 2, 3]]

    问题定位

    rightPushAll有两个重载方法:第一个方法values形参的接收参数是一个可变长度的泛型参数列表,第二个方法values形参的接收参数是泛型的Collection。

    	/*
    	 * (non-Javadoc)
    	 * @see org.springframework.data.redis.core.ListOperations#rightPushAll(java.lang.Object, java.lang.Object[])
    	 */
    	@Override
    	public Long rightPushAll(K key, V... values) {
    
    		byte[] rawKey = rawKey(key);
    		byte[][] rawValues = rawValues(values);
    		return execute(connection -> connection.rPush(rawKey, rawValues));
    	}
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.springframework.data.redis.core.ListOperations#rightPushAll(java.lang.Object, java.util.Collection)
    	 */
    	@Override
    	public Long rightPushAll(K key, Collection<V> values) {
    
    		byte[] rawKey = rawKey(key);
    		byte[][] rawValues = rawValues(values);
    		return execute(connection -> connection.rPush(rawKey, rawValues));
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    因为调用方法实参values是一个List,从语法上来说,两个重载方法是都可以调到的。因为重载是Java编译时的多态性,那么编译器编译时会调用哪个方法呢?实参ArrayList实现了Collection接口,所以误认为会走rightPushAll(K key, Collection values)方法,但是Collection是带泛型的,RedisTemplate的value指定的泛型是Object,存值时保存的ArrayList指定的泛型却是String,虽然String继承了Object,但是编辑器编辑时还是会优先选择调用rightPushAll(K key, V... values)进行编译。可以通过打断点或者查看字节码文件验证,确实调用的是rightPushAll(K key, V... values)方法。生成的字节码文件

    解决方案:

    RedisTemplate 指定的value值和传入的value值的泛型类型保持一致。比如上文中的例子,只需将 private RedisTemplate redisTemplate;改为private RedisTemplate redisTemplate;或者 RedisTemplate不变将ArrayList arrayList = new ArrayList<>();改为ArrayList arrayList = new ArrayList<>();

    问题疑惑

    为什么编译器会优先走rightPushAll(K key, V... values)方法?重载的顺序到底是怎么样的?特别是泛型或者可变参数列表的形参,编译的原理是怎样的?欢迎有答案的小伙伴给我留言或者粘贴相关资料链接

  • 相关阅读:
    API接口与电商平台之间的联系,采集京东平台数据按关键字搜索商品接口示例
    Prompt-Tuning源码分析
    深入理解依赖倒置原则(Dependence Inversion Principle)
    计算机网络体概念
    【Redis】zset常用命令&集合间操作&内部编码&使用场景
    容灾演练月报 | 雅安市商业银行四大业务系统完成容灾切换演练
    paddleocr的cpp_infer在Liunx下编译部署
    kafka消费者模式
    R语言最优聚类数目k改进kmean聚类算法
    openssl/rc4.h: 没有那个文件或目录
  • 原文地址:https://blog.csdn.net/qq719779232/article/details/126147002
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号