java如何拷贝复制对象和集合问题

 更新时间:2023年09月27日 08:39:45   作者:Yang疯狂打码中  
这篇文章主要介绍了java如何拷贝复制对象和集合问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

在Java中常见的对象拷贝方式是使用cglib,Cglib的性能是目前公认最好的,用于解决Bean拷贝的性能问题

下面是以cglib封装的工具类实现对象和集合的拷贝

一、引入依赖

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

二、创建CglibUtil工具类

其中包含对象和集合的拷贝,还封装了Bean转Map的方法

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.beans.BeanMap;
import net.sf.cglib.core.Converter;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
 * @author YangBoss
 * @title: CglibUtil
 * @projectName frontop-ao
 * @description: CglibUtil工具类
 * @date 2022/6/2 10:18
 */
public class CglibUtil {
    /**
     * 拷贝Bean对象属性到目标类型<br>
     * 此方法通过指定目标类型自动创建之,然后拷贝属性
     *
     * @param <T>         目标对象类型
     * @param source      源bean对象
     * @param targetClass 目标bean类,自动实例化此对象
     * @return 目标对象
     */
    public static <T> T copy(Object source, Class<T> targetClass) {
        return copy(source, targetClass, null);
    }
    /**
     * 拷贝Bean对象属性<br>
     * 此方法通过指定目标类型自动创建之,然后拷贝属性
     *
     * @param <T>         目标对象类型
     * @param source      源bean对象
     * @param targetClass 目标bean类,自动实例化此对象
     * @param converter   转换器,无需可传{@code null}
     * @return 目标对象
     */
    public static <T> T copy(Object source, Class<T> targetClass, Converter converter) {
        final T target = ReflectUtil.newInstanceIfPossible(targetClass);
        copy(source, target, converter);
        return target;
    }
    /**
     * 拷贝Bean对象属性
     *
     * @param source 源bean对象
     * @param target 目标bean对象
     */
    public static void copy(Object source, Object target) {
        copy(source, target, null);
    }
    /**
     * 拷贝Bean对象属性
     *
     * @param source    源bean对象
     * @param target    目标beBeanCopierCachean对象
     * @param converter 转换器,无需可传{@code null}
     */
    public static void copy(Object source, Object target, Converter converter) {
        Assert.notNull(source, "Source bean must be not null.");
        Assert.notNull(target, "Target bean must be not null.");
        final Class<?> sourceClass = source.getClass();
        final Class<?> targetClass = target.getClass();
        boolean conIsNull = converter == null ? false : true;
        final BeanCopier beanCopier = BeanCopier.create(sourceClass, targetClass, conIsNull);
        beanCopier.copy(source, target, converter);
    }
    /**
     * 拷贝List Bean对象属性
     *
     * @param <S>    源bean类型
     * @param <T>    目标bean类型
     * @param source 源bean对象list
     * @param target 目标bean对象
     * @return 目标bean对象list
     */
    public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target) {
        return copyList(source, target, null, null);
    }
    /**
     * 拷贝List Bean对象属性
     *
     * @param source    源bean对象list
     * @param target    目标bean对象
     * @param converter 转换器,无需可传{@code null}
     * @param <S>       源bean类型
     * @param <T>       目标bean类型
     * @return 目标bean对象list
     * @since 5.4.1
     */
    public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, Converter converter) {
        return copyList(source, target, converter, null);
    }
    /**
     * 拷贝List Bean对象属性
     *
     * @param source   源bean对象list
     * @param target   目标bean对象
     * @param callback 回调对象
     * @param <S>      源bean类型
     * @param <T>      目标bean类型
     * @return 目标bean对象list
     * @since 5.4.1
     */
    public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, BiConsumer<S, T> callback) {
        return copyList(source, target, null, callback);
    }
    /**
     * 拷贝List Bean对象属性
     *
     * @param source    源bean对象list
     * @param target    目标bean对象
     * @param converter 转换器,无需可传{@code null}
     * @param callback  回调对象
     * @param <S>       源bean类型
     * @param <T>       目标bean类型
     * @return 目标bean对象list
     */
    public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, Converter converter, BiConsumer<S, T> callback) {
        return source.stream().map(s -> {
            T t = target.get();
            copy(s, t, converter);
            if (callback != null) {
                callback.accept(s, t);
            }
            return t;
        }).collect(Collectors.toList());
    }
    /**
     * 将Bean转换为Map
     *
     * @param bean Bean对象
     * @return {@link BeanMap}
     * @since 5.4.1
     */
    public static BeanMap toMap(Object bean) {
        return BeanMap.create(bean);
    }
}

三、测试拷贝对象和集合

拷贝对象测试,再将拷贝的对象和源对象放入集合中对拷贝集合测试

 public static void main(String[] args) {
        /**
         * 拷贝对象
         */
        //创建对象
        TUser tUser  = new TUser();
        tUser.setName("李四");
        //拷贝对象
        TUser tUser2 = CglibUtil.copy(tUser,TUser.class);
        //打印结果
        System.out.println(tUser2.getName());
        /**
         * 拷贝集合
         */
        //创建集合
        List<TUser> list1 = new ArrayList<>();
        list1.add(tUser);
        list1.add(tUser2);
        //拷贝集合
        List<TUser> list2 = CglibUtil.copyList(list1,TUser::new);
        //打印结果
        System.out.println(JSONObject.toJSONString(list2));
    }

结果打印

四、注意点

CglibUtil.copy拷贝对象的时候,目标对象被lombok注解@Accessors(chain = true)修饰报空指针

在拷贝对象上不可用注解 @Accessors ,反射获取不到对应的setter,因为这个链式生成的代码带了返回值,此注解会将set方法返回值改变

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java树形菜单的创建

    Java树形菜单的创建

    这篇文章主要为大家详细介绍了Java图形用户界面中树形菜单的创建树形菜单的创建,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-10-10
  • 使用Spring Boot搭建Java web项目及开发过程图文详解

    使用Spring Boot搭建Java web项目及开发过程图文详解

    这篇文章主要介绍了使用Spring Boot搭建Java web项目及开发过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理

    Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理

    AtomicLongFieldUpdater可以对指定"类的 'volatile long'类型的成员"进行原子更新。它是基于反射原理实现的。下面通过本文给大家分享Java concurrency之AtomicLongFieldUpdater原子类的相关知识,感兴趣的朋友一起看看吧
    2017-06-06
  • 手写一个@Valid字段校验器的示例代码

    手写一个@Valid字段校验器的示例代码

    这篇文章主要为大家详细介绍了如何手写一个@Valid字段校验器,文中的示例代码讲解详细,对我们学习有一定帮助,需要的可以参考一下
    2022-07-07
  • Java 8中读取文件内容 Files.lines()方法使用示例

    Java 8中读取文件内容 Files.lines()方法使用示例

    这篇文章主要介绍了Java 8中读取文件内容Files.lines()方法如何使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • mybatis参数类型不匹配错误argument type mismatch的处理方案

    mybatis参数类型不匹配错误argument type mismatch的处理方案

    这篇文章主要介绍了mybatis参数类型不匹配错误argument type mismatch的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java Set集合去重的原理及实现

    Java Set集合去重的原理及实现

    这篇文章主要介绍了Java Set集合去重的原理及实现,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java通过递归算法解决迷宫与汉诺塔及八皇后问题

    Java通过递归算法解决迷宫与汉诺塔及八皇后问题

    方法就是用来完成解决某件事情或实现某个功能的办法;程序调用自身的编程技巧称为递归,本文主要讲的是通过递归来实现三个经典的问题,解决迷宫,汉诺塔,八皇后问题,感兴趣的朋友可以参考一下
    2022-05-05
  • Spring使用注解实现Bean的自动装配

    Spring使用注解实现Bean的自动装配

    大家好,本篇文章主要讲的是Spring使用注解实现Bean的自动装配,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • springcloud feign 接口指定接口服务ip方式

    springcloud feign 接口指定接口服务ip方式

    这篇文章主要介绍了springcloud feign 接口指定接口服务ip方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论