对象bean与map互转问题(代码片段)

yrjns yrjns     2023-04-15     368

关键词:

一、摘要

在实际开发过程中,经常碰到需要进行对象与map之间互转的问题,其实对于对象、Map 之间进行互转有很多种方式,下面我们一起来梳理一下:

  • 利用 JSON 工具包,将对象转成字符串,之后再转成 Map,这种需要转换2次,相对来说效率比较底;
  • 利用 Java 反射,获取 Bean 类的属性和值,再转换到 Map 对应的键值对中,相对来说这种方法效率高些,在实现上比较麻烦;
  • 利用 Java 的内省(Introspector) 实现,获取 Bean 类的属性和值,Map与对象互转,效率比较高;
  • 利用 apache 中的 BeanUtils工具包进行操作,底层实现类似方法三;
  • 利用net.sf.cglib.beans.BeanMap类中的方法,这种方式效率也非常高;

 

二、常用方法

也不多说了,直接show code,为了更接近实际场景,我们新建两个实体类UserRole,假设一个用户有多个角色,如下:

publicclass User 

    private String userId;

    private String userName;

    private List<Role> roleList;

    //... 省略 setter 和 getter

    public User() 

    public User(String userId, String userName) 
        this.userId = userId;
        this.userName = userName;
    

publicclass Role 

    private String userId;

    private String roleName;

    //... 省略 setter 和 getter

    public Role(String userId, String roleName) 
        this.userId = userId;
        this.roleName = roleName;
    

 

 

2.1、通过 JSON 进行转换

在这里,我们利用阿里巴巴的fastjson包进行转换,通过maven引入 jar,如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.49</version>
</dependency>

 

方法如下:

publicclass BeanMapUtilByJson 

    /**
     * 对象转Map
     * @param object
     * @return
     */
    public static Map beanToMap(Object object)
        return JSONObject.parseObject(JSON.toJSONString(object),Map.class);
    

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     */
    publicstatic <T> T mapToBean(Map map, Class<T> beanClass)
        return JSONObject.parseObject(JSON.toJSONString(map),beanClass);
    

 

2.2、利用反射进行转换

这种操作是利用 java 原生提供的反射特性来实现互转,方法如下:

 

publicclass BeanMapUtilByReflect 

    /**
     * 对象转Map
     * @param object
     * @return
     * @throws IllegalAccessException
     */
    public static Map beanToMap(Object object) throws IllegalAccessException 
        Map<String, Object> map = new HashMap<String, Object>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) 
            field.setAccessible(true);
            map.put(field.getName(), field.get(object));
        
        return map;
    

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    publicstatic <T> T mapToBean(Map map, Class<T> beanClass) throws Exception 
        T object = beanClass.newInstance();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) 
            int mod = field.getModifiers();
            if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) 
                continue;
            
            field.setAccessible(true);
            if (map.containsKey(field.getName())) 
                field.set(object, map.get(field.getName()));
            
        
        return object;
    

 

2.3、利用内省机制进行转换

内省(Introspector)是 Java 语言对 JavaBean 类属性、事件的一种缺省处理方法,也是基于 java 原生实现,操作如下:

 

publicclass BeanMapUtilByIntros 

    /**
     * 对象转Map
     * @param object
     * @return
     */
    public static Map beanToMap(Object object) throws Exception 
        Map<String, Object> map = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) 
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) 
                continue;
            
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(object) : null;
            map.put(key, value);
        
        return map;
    

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    publicstatic <T> T mapToBean(Map map, Class<T> beanClass) throws Exception 
        T object = beanClass.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) 
            Method setter = property.getWriteMethod();
            if (setter != null) 
                setter.invoke(object, map.get(property.getName()));
            
        
        return object;
    

 

2.4、利用 apache 中的 BeanUtils 进行转换

在使用这个方法前,需要手动引入 apache 中的 beanutils 包,方法如下:

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

想必大家都不会陌生,操作如下:

publicclass BeanMapUtilByApache 

    /**
     * 对象转Map
     * @param object
     * @return
     */
    public static Map beanToMap(Object object)
        returnnew org.apache.commons.beanutils.BeanMap(object);
    

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     */
    publicstatic <T> T mapToBean(Map map, Class<T> beanClass) throws Exception 
        T object = beanClass.newInstance();
        org.apache.commons.beanutils.BeanUtils.populate(object, map);
        return object;
    

 

2.5、利用 cglib 中的 BeanMap 进行转换

在使用这个方法前,需要手动引入cglib 包,方法如下:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

 

Spring 内置了 cglib,在项目中经常看到有同学用这个方法,操作如下:

 

publicclass BeanMapUtilByCglib 

    /**
     * 对象转Map
     * @param object
     * @return
     */
    public static Map beanToMap(Object object)
        Map<String, Object> map = new HashMap<String, Object>();
        if (object != null) 
            BeanMap beanMap = BeanMap.create(object);
            for (Object key : beanMap.keySet()) 
                map.put(key+"", beanMap.get(key));
            
        
        return map;
    

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    publicstatic <T> T mapToBean(Map map, Class<T> beanClass) throws Exception 
        T bean = beanClass.newInstance();
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    

 

2.6、测试

上面介绍完了操作,最后我们来测试一下,新建一个测试客户端TestClient,分别测试上面5个工具类

publicclass BeanMapClient 

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) 
        //为了更贴近实际场景,构造嵌套实体对象
        User user = new User("1","张三");
        List<Role> roleList = new ArrayList<Role>();
        roleList.add(new Role("1","技术经理"));
        roleList.add(new Role("1","信息主任"));
        user.setRoleList(roleList);
        //bean转map
        Map userMap = BeanMapUtilByJson.beanToMap(user);
        System.out.println("转换后的map:" + JSON.toJSONString(userMap));
        //修改源对象中信息
        user.getRoleList().get(0).setRoleName("项目经理");
        user.getRoleList().add(new Role("1","项目经理"));
        //map转bean
        User newUser = BeanMapUtilByJson.mapToBean(userMap,User.class);
        System.out.println("转换后的bean:" + JSON.toJSONString(newUser));
    

 

输出结果如下:

技术图片

 

 

对上面5中输出结果进行分析,可以得出如下结论:

  • 将对象转换成map,基本都一致,将map转成bean的时候,有些小区别;
  • 方法一,通过json转换后的bean对象,即使源对象发生改变,转换后的对象不会发生变化,这是因为json在底层转换bean时,都创建了新的对象;
  • 方法二、三、四、五,当源对象有嵌套对象,修改嵌套对象,也就是Role内容,转换后的对象也会随之发生改变;

从结果可以看出,方法一、二、三、四、五,都可以进行对象与 map 的互转,那他们到底有啥区别呢?

下面我们从性能角度来观察一下,使用for循环测试 map 与对象的互转,结果如下:

 

技术图片

 

 

可能每个机器的性能不一样,这个是我的电脑上测试的结果,从数据上可以看出:

  • 性能最好的是反射方法,其次就是内省方法,这两个方法都没有引用第三方jar包,所以相对可能要快点;
  • 使用第三方引用中,cglib 效率还可以,其次 apache的beanUtils工具包,最后就是Json包;

 

三、总结

如果对性能要求很高,可以采用 java 原生编程实现对象与 map 的互转,如果已经引用了 apache 或者 cglib 的jar,可以利用它提供的方法进行转换,优先推荐使用 cglib,因为 Spring 已经继承了 cglib,在项目中可以直接使用!

 

 

原文链接:https://mp.weixin.qq.com/s/6dq6aKfV1GKLOvD-RGmcpw

 

java--map与实体类对象之间互转(代码片段)

一、json转换依赖阿里的FastJSon,用到的主要jar包:fastjson-1.2.54.jar1、maven引入<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.54 查看详情

[转]解析json:与array,list,map,bean,xml相互转化

...用netsfjson需要导入的包JSONObjectJSONArrayJavaBean与json字符串互转List与json字符串互转Map与json字符串互转JSONArray与List互转JSONArray与数组互转XML与JSON互转  下载地址[plain] viewplain cop 查看详情

java对象与json字符串的互转(代码片段)

JSON字符串转普通对象普通对象转JSON字符串JSON字符串数组转List集合对象List集合对象转JSON字符串数组JSON字符串转装有对象的Map装有对象的Map转JSON字符串最近,工作中会涉及到Java对象与JSON字符串相互转换,虽然说并不难&... 查看详情

转:json与map互转(代码片段)

转自:java中字符串,json,Map互相转换(各种转换都有)_蜗牛驿站-CSDN博客_javajson转map前提:使用jar包为fastjsonimportcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.JSONObject; 程序如下:    Map 查看详情

008-treemapmap和bean互转beanutils.copyproperties(a,b)拷贝url编码解码字符串补齐(代码片段)

1、TreeMap 有序Map  无序有序转换  使用默认构造方法:publicTreeMap(Map<?extendsK,?extendsV>m)2、Map和Bean互转BeanUtils位于org.apache.commons.beanutils.BeanUtils下面,其方法populate的作用解释如下:完整方法:BeanUtils.populate(Objectbe 查看详情

flutter的map与string互转(存入sharedpreferences)(代码片段)

Hello,I’Shendi这里记录一下我的需求是将Map中的数据存到SharedPreferences中,下次初始化时取出来转换成MapMap与JSONObject格式差不多一致,可以直接这样创建一个MapMapm="key":"value";在Flutter中,对于JSONObject字符... 查看详情

flutter的map与string互转(存入sharedpreferences)(代码片段)

Hello,I’Shendi这里记录一下我的需求是将Map中的数据存到SharedPreferences中,下次初始化时取出来转换成MapMap与JSONObject格式差不多一致,可以直接这样创建一个MapMapm="key":"value";在Flutter中,对于JSONObject字符... 查看详情

flutter的map与string互转(存入sharedpreferences)(代码片段)

Hello,I’Shendi这里记录一下我的需求是将Map中的数据存到SharedPreferences中,下次初始化时取出来转换成MapMap与JSONObject格式差不多一致,可以直接这样创建一个MapMapm="key":"value";在Flutter中,对于JSONObject字符... 查看详情

java中map和对象互转工具类的实现示例

在项目开发中,经常碰到map转实体对象或者对象转map的场景,工作中,很多时候我们可能比较喜欢使用第三方jar包的API对他们进行转化,而且用起来也还算方便,比如像fastJson就可以轻松实现map和对象的互转,但这里,我想通过... 查看详情

使用bean其实优于map(代码片段)

...里,一直以为使用反射技术效率低,对比于使用反射创建对象,可能直接创建Map更快,但是这种认知是错误的,以下以创建一百万个对象为例 packagespring;importjava.lang.reflect.Field;importjava.util.ArrayList;importjava.util.HashMap;importjava.uti... 查看详情

使用beanutils.populate将map集合封装为bean对象(代码片段)

...t.getParameterMap配合使用可以将jsp页面表单的数据转化为bean对象。2.介绍BeanUtils位于org.apache.commons.beanutils.BeanUtils下面,其方法populate的作用解释如下:完整方法:BeanUtils.populate(Objectbean,Mapproperties),这个方法会遍历map<key,value>... 查看详情

xstream进行xml和bean互转(代码片段)

加入pom<dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.3</version></dependency>最简单的使用方式XStreamxStream= 查看详情

jsonjavabeanmapxml之间的互转(代码片段)

思路是JavaBean、Map、XML都可以用工具类很简单的转换为Json,进而实现互相转换1.Map、XML与Json互转mvn依赖<dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20171018</version 查看详情

java一个对象赋值给另一个对象,支持平铺类和层级类间的互转(代码片段)

场景:将一个层级类对象(领域驱动model对象)转换为平铺类对象(view)src对象,(红框为子对象)target对象(平铺对象)代码思路,先递归反射遍历出所有字段,存到一个map里,再递归赋值给target对象缺陷:不同子对象间的同名字... 查看详情

java工具类--map转bean各bean转map(代码片段)

publicclassBeanMapUtils/***将对象属性转化为map结合*/publicstatic<T>Map<String,Object>beanToMap(Tbean)Map<String,Object>map=newHashMap<>();if(bean!=null)BeanMapbeanMap=Bean 查看详情

xml转bean(代码片段)

XML转Bean有很多方式,我使用的是xtream方式实现xml与bean的互转。下面是简单的xml转bean/***XML转换成bean*@paramobj*@returnyuyuchen*/publicstaticObjectXmlTojavaBean(StringxmlOut)Objectobject=null;tryClass<?>cl=Class.forName(xmlO 查看详情

json串与java对象互转

Json与Bean互转,Timestamp类型的问题:http://blog.csdn.net/luckdog_hot/article/details/78808761)将java单个对象装换成json串   2)将java集合对象转换成json串   3:将json串装换成java单个对象     查看详情

json对象互转问题记录(代码片段)

...的问题在项目里面前端接收的一个string类型的json转换成对象的时候报错cn.hutool.core.convert.ConvertException:NoConverterfortype[java.util.List]然后不服气的我拿出来研究了一下,结果发现在新建的工程里面没有问题。这就很尴尬了。本着... 查看详情