码农知识堂 - 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)方法?重载的顺序到底是怎么样的?特别是泛型或者可变参数列表的形参,编译的原理是怎样的?欢迎有答案的小伙伴给我留言或者粘贴相关资料链接

  • 相关阅读:
    java通过Thread类实现多线程方法
    工程师如何对待开源
    虹科方案 | 虹科ATTO加速虚拟存储管理
    JAVA类加载器
    Perl动态建立ZIP压缩文件
    化工园区数字孪生可视化管控平台,赋予园区安全环保智慧发展
    第8章_瑞萨MCU零基础入门系列教程之SCI SPI
    Spark Streaming概述
    WPF 上位机 Modbus 入门必备的信息 C# 开发对接
    极光魔链(JMLink)使用教程
  • 原文地址:https://blog.csdn.net/qq719779232/article/details/126147002
    • 最新文章
    • 沪漂五周年了:我越来越迷茫了
      Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
      MySQL-Seconds_behind_master的精度误差
      [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
      AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
      Agent OS :五种驯服不确定性的范式
      PortSwigger SQL注入LAB11
      数据库即时编译JIT
      [Begin]AI Learn Data Day 0
      深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    小工具 小游戏
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

    京公网安备 11010502049817号