从永远到永远-Map传值的坑map.values()

博客讲述了在Java中从Map获取values并转换为List时遇到的ClassCastException错误,以及如何通过转换为Collection再构造List来解决这个问题。强调了避免使用Map作为参数传递,因其不利于维护且易引发类型转换问题。

Map传值的坑map.values

1.需求

将某接口中返回的数组,根据某字段进行排序取前三条。为不与原处理逻辑耦合(不想看祖传代码,更不想在祖传代码中留下操作痕迹),直接在返回数据前,将数组取出排序,重新设置进去。
结果,正因为没有仔细看代码并且对这个世界怀揣美好的幻想,程序华丽丽地报错了。

2.错误

java.lang.ClassCastException: java.util.HashMap$Values cannot be cast to java.util.List

浅显易懂,hashMap的values不能转成List。忍着恶心,我看了看代码。说真的,我还是低估一个同事的想象力。map封装反参,就算了。这个数组,不是List不是数组。而是先将n个map封装到一个map中,之后将map.values()封装到了返回数组中。如图,示例代码:
在这里插入图片描述

3.解决

看下源码,map.values返回的是Collection。
在这里插入图片描述
那就先转成Collection。处理如下
在这里插入图片描述
完整实例代码

Map<String, Object> returnMap = new HashMap<>();
        Map<String, Map
明白了,你是通过 `Map` 参的方式将参数入 MyBatis 的 SQL 映射文件中,而你遇到的问题是:**当入的 `int` 类型为 0 时,MyBatis 误将其识别为 null 或者未正确处理**。 这个问题的核心在于: - Java 中 `int` 是基本类型,不能为 `null`。 - 如果你是从 `Map<String, Object>` 入的,`int` 会被自动装箱为 `Integer`。 - 在 MyBatis 的 `<if test="xxx != null">` 中,如果入的是 `int`,MyBatis 会自动将其转换为 `Integer`,但某些情况下判断逻辑可能会出错。 --- ### ✅ 问题重现示例 假设你入的是: ```java Map<String, Object> params = new HashMap<>(); params.put("age", 0); ``` 然后你的 XML 中有: ```xml <insert id="insertUser"> INSERT INTO user (age) VALUES ( <if test="age != null"> #{age} </if> ) </insert> ``` 由于你入的是 `int` 类型的 `0`,会被自动装箱为 `Integer`,所以 `age != null` 是成立的,但如果你入的是 `null`(即 `params.put("age", null)`),那么就会被判断为 `null`。 --- ### ✅ 正确写法 #### ✅ 方法一:使用 `<if test="age != null">` 判断 `Integer` 如果你入的是 `Map<String, Object>`,MyBatis 会自动处理 `Integer` 类型。建议你入 `null` 或 `Integer` 类型来区分空和 0。 ```java Map<String, Object> params = new HashMap<>(); params.put("age", 0); // 正常插入 0 // 或 params.put("age", null); // 插入 NULL ``` XML: ```xml <insert id="insertUser"> INSERT INTO user (age) VALUES ( <if test="age != null"> #{age} </if> <if test="age == null"> NULL </if> ) </insert> ``` --- #### ✅ 方法二:使用 `<choose>` 判断 如果你想根据 `0` 插入 `NULL`,可以使用 `<choose>`: ```xml <insert id="insertUser"> INSERT INTO user (age) VALUES ( <choose> <when test="age == 0"> NULL </when> <otherwise> #{age} </otherwise> </choose> ) </insert> ``` > 注意:`age == 0` 要求 `age` 是 `Integer` 类型,不能是 `null`,否则会报错。 --- #### ✅ 方法三:安全判断(处理 null 和 0) 为了更安全地处理 null 和 0,可以这样写: ```xml <insert id="insertUser"> INSERT INTO user (age) VALUES ( <choose> <when test="age == null"> NULL </when> <when test="age == 0"> NULL </when> <otherwise> #{age} </otherwise> </choose> ) </insert> ``` 这样无论是 `null` 还是 `0`,都会插入 `NULL`,其他正常插入。 --- ### ✅ JDBCType 建议 如果你在插入时遇到类型问题,可以显式指定 `jdbcType`: ```xml #{age, jdbcType=INTEGER} ``` 这样可以避免类型推断错误。 --- ### ✅ 总结 | 问题原因 | 解决方案 | |----------|----------| | 使用 `int` 时无法判断 null | 改为 `Integer` | | `<if test="age != null">` 失效 | 使用 `<choose>` 显式判断 | | 插入 `0` 想变成 `NULL` | 使用 `<choose>` 或 `<when>` 判断 | | 避免类型识别错误 | 使用 `jdbcType=INTEGER` | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值