map和object相互转换的几种方法和对比
时间:2022-07-23
本文章向大家介绍map和object相互转换的几种方法和对比,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
工作中经常遇到这样的场景,需要在object和map直接相互转换,这里总结一下。
我先定义一个实体类,后面介绍的几种转换方法都以这个实体类为例进行说明。
1public class PersonBean {
2 private String name; //姓名
3 private Integer age; //年龄
4 private Boolean boy; //是否男孩
5 private Date birthday; //生日
6}
这里尽量覆盖不同的属性类型,便于全面的测试转换方法。
第一种方法,利用反射
1
然后我们写个测试方法验证一下,
1@Test
2 public void test1() throws Exception {
3 Map<String, Object> map = new HashMap<String, Object>();
4 map.put("name", "fcbox");
5 map.put("age", 15);
6 map.put("boy", true);
7 map.put("birthday", new Date());
8
9 PersonBean person = (PersonBean)map2Object_1(map, PersonBean.class);
10 System.out.println("方法1 map->object的转换结果:" + person);
11 Map<String, Object> newMap = Object2Map_1(person);
12 System.out.println("方法1 object->map的转换结果:" + JSON.toJSONString(newMap));
13 }
输出,
1方法1 map->object的转换结果:PersonBean(name=fcbox, age=15, boy=true, birthday=Wed Nov 06 14:52:57 CST 2019)
2方法1 object->map的转换结果:{"birthday":1573023177881,"name":"fcbox","boy":true,"age":15}
然后我们接着做个测试,把
1map.put("boy", true);
改成
1map.put("boy", "true");
会报异常,
1java.lang.IllegalArgumentException: Can not set java.lang.Boolean field com.pony.app.PersonBean.boy to java.lang.String
2 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
3 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
4 at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
5 at java.lang.reflect.Field.set(Field.java:758)
6 at com.pony.test.Map2ObjectTest.map2Object_1(Map2ObjectTest.java:66)
7 at com.pony.test.Map2ObjectTest.test1(Map2ObjectTest.java:33)
8 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
10 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11 at java.lang.reflect.Method.invoke(Method.java:483)
12 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
13 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
14 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
15 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
16 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
17 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
18 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
19 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
20 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
21 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
22 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
23 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
24 at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
25 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
26 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
27 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
28 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
29 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
30方法1 map->object的转换结果:PersonBean(name=fcbox, age=15, boy=null)
你可以先记住这个结论,继续往下看。
第二种方法,利用commons.BeanUtils
示例代码如下:
1public static Object map2Object_2(Map<String, Object> map, Class<?> clazz) {
2 if (map == null) {
3 return null;
4 }
5 Object obj = null;
6 try {
7 obj = clazz.newInstance();
8 //这个方法会遍历map<key, value>中的key,如果bean中有这个属性,就把这个key对应的value值赋给bean的属性。
9 BeanUtils.populate(obj, map);
10 } catch (Exception e) {
11 e.printStackTrace();
12 }
13 return obj;
14 }
15
16 public static Map<?, ?> Object2Map_2(Object object) {
17 if (object == null) {
18 return null;
19 }
20
21 return new BeanMap(object);
22 }
测试方法,
1@Test
2 public void teste2(){
3
4 Map<String, Object> map = new HashMap<String, Object>();
5 map.put("name", "tom");
6 map.put("age", 15);
7 map.put("boy", true);
8 map.put("birthday", new Date());
9
10 PersonBean person = (PersonBean)map2Object_2(map, PersonBean.class);
11 System.out.println("方法2 map->object的转换结果:" + person);
12 Map<?, ?> newMap = Object2Map_2(person);
13 System.out.println("方法2 object->map的转换结果:" + JSON.toJSONString(newMap));
14 }
输出,
1方法2 map->object的转换结果:PersonBean(name=tom, age=15, boy=true, birthday=Wed Nov 06 14:53:47 CST 2019)
2方法2 object->map的转换结果:{"birthday":1573023227193,"name":"tom","boy":true,"class":"com.pony.app.PersonBean","age":15}
然后像上个示例一样,把
1map.put("boy", true);
改成
1map.put("boy", "true");
你会发现依然可以正确的输出同样的结果。
从这点来看,beanutils比反射好用,它里面做了大量的转换工作,反射的方法更多需要你自己来处理。
第三种方法,json转换
这里使用 fastjson,其实用其它的组件也是可以的。
1public static Object map2Object_3(Map<String, Object> map, Class<?> clazz) {
2 if (map == null) {
3 return null;
4 }
5 return JSON.parseObject(JSON.toJSONString(map), clazz);
6 }
7
8 public static Map<?, ?> Object2Map_3(Object object) {
9 if (object == null) {
10 return null;
11 }
12 return JSON.parseObject(JSON.toJSONString(object), Map.class);
13 }
测试方法,
1@Test
2 public void test3(){
3
4 Map<String, Object> map = new HashMap<String, Object>();
5 map.put("name", "tom");
6 map.put("age", 15);
7 map.put("boy", true);
8 map.put("birthday", new Date());
9
10 PersonBean person = (PersonBean)map2Object_3(map, PersonBean.class);
11 System.out.println("方法3 map->object的转换结果:" + person);
12 Map<?, ?> newMap = Object2Map_3(person);
13 System.out.println("方法3 object->map的转换结果:" + JSON.toJSONString(newMap));
14 }
输出,
1方法3 map->object的转换结果:PersonBean(name=tom, age=15, boy=true, birthday=Wed Nov 06 15:30:47 CST 2019)
2方法3 object->map的转换结果:{"birthday":1573025447719,"name":"tom","boy":true,"age":15}
json的方法似乎也不错,它的原理是先把map转成json,然后把json转成object。而且你可以测试下,它也是可以识别 map.put("boy", "true");
这种赋值方式的。
性能问题
我在上面三个测试方法上增加耗时打印,发现三个方法的性能排名是:
方法1 > 方法3 > 方法2
也就是说,方法2最耗时。当然这个不是官方结论,只是我自己本地环境测试的结果。
- 设置WPF窗体全屏显示:
- winform 、WPF传值方式详解
- 你一定要知道!数据科学家提高工作效率的基本工具
- MySQL 大数据操作注意事项
- Winform窗口里的嵌入WPF的UserControl,关闭Winform父窗体的方法
- LINQ分页和排序,skip和Take 用法
- 这或许是对小白最友好的python入门了吧——21,导入模块
- opoa介绍
- 数据库记录安全解决方案
- 基于计算机视觉和OpenCV:创建一个能够计算道路交通流量的应用
- 这或许是对小白最友好的python入门了吧——20,定义函数简单应用
- 数据库结构版本控制
- Extjs4---Cannot read property 'addCls' of null 或者 el is null 关于tab关闭后再打开不显示或者报错
- 【干货】什么?Python3.X不能输出中文?原来是编辑器geany的锅?!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 多目标优化拥挤距离计算
- matlab sort函数
- matlab结构体的创建与元素访问
- matlab赋值运算符等号
- Flutter中Widget 、Element、RenderObject角色深入分析
- PyTorch8:损失函数
- 浅谈ThreadLocal
- 三分钟完成 ubuntu16.04初始化,Java,maven,docker环境的部署
- VMware 安装运行 deepin 虚拟机 | 体验中国深度
- 单机KVM虚拟化快照定时创建删除快照
- 批量ping脚本
- 批量ssh信任脚本
- Oracle表级备份
- Linux脚本运行报错解决方法 bad interpreter: No such file or directory
- MySQLdump里的秘密,终于被我发现了