Java中对象/嵌套对象属性复制工具类使用示例:Hutools工具类BeanUtils使用示例
场景
Java对象集合复制工具类有多种方案:
1、Java中使用MapStruct实现对象转换/实体属性赋值/Bean属性映射,避免大量setter和getter:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/128922752
2、Spring BeanUtils(Spring生态标配)
List<UserDTO> dtos = new ArrayList<>();
entities.forEach(src -> {UserDTO target = new UserDTO();BeanUtils.copyProperties(src, target); // 浅拷贝dtos.add(target);
});
不支持集合类型自动转换
嵌套对象需手动处理
3、Apache Commons BeanUtils(传统方案)
兼容老旧系统
List<UserDTO> dtos = entities.stream().map(src -> {UserDTO target = new UserDTO();BeanUtils.copyProperties(target, src); // 注意参数顺序!return target;}).toList();
性能较差(10万次约450ms)
需手动处理集合转换
4、Hutool BeanUtil
快速开发、字段名基本一致
支持@Alias注解处理字段别名
自动处理String↔Date等常见类型转换
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
实现
简单使用示例
import cn.hutool.core.annotation.Alias;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Arrays;
import java.util.Date;
import java.util.List;public class HutoolsCopyCollectionUtilsDemo {@Data@NoArgsConstructorprivate static class UserEntity {private Long id;private String userName; // 字段名与DTO不同private Integer age;private Date createTime;private String extraJson; // 需要特殊处理的JSON字段// 嵌套对象示例private Department dept;UserEntity(String userName, Integer age) {this.userName = userName;this.age = age;};UserEntity(String userName, Integer age,Department dept) {this.userName = userName;this.age = age;this.dept = dept;};}@Dataprivate static class Department {private String deptCode;private String deptName;Department(){}Department(String deptCode, String deptName) {this.deptCode = deptCode;this.deptName = deptName;};}@Dataprivate static class UserDTO {@Alias("userName") // 映射实体类的userName字段private String name;private Integer age;private String createTime;// 嵌套DTOprivate DeptDTO department;// 从JSON解析的字段private List<String> permissions;private String extraJson;}@Dataprivate static class DeptDTO {@Alias("deptCode")private String code;private String name;}public static void main(String[] args) {//简单对象复制UserEntity entity = new UserEntity();entity.setUserName(" 张三");entity.setAge(25);// 基础复制(自动处理@Alias注解)UserDTO dto = BeanUtil.copyProperties(entity, UserDTO.class);System.out.println(dto.getName()); // 输出"张三"System.out.println(dto);//集合批量复制List<UserEntity> entities = Arrays.asList(new UserEntity("李四",30),new UserEntity("王五",20));//集合复制(自动类型转换)List<UserDTO> userDOS = BeanUtil.copyToList(entities, UserDTO.class);System.out.println(userDOS);//自定义类型转换器// 注册全局转换器(Date -> String)UserEntity entity1 = new UserEntity();entity1.setUserName("赵六");entity1.setCreateTime(new Date());UserDTO dto1 = new UserDTO();BeanUtil.copyProperties(entity1, dto1,new CopyOptions().setFieldValueEditor((fieldName, fieldValue) -> {if (fieldValue instanceof Date) {return DateUtil.format((Date)fieldValue, "yyyy-MM-dd");}return fieldValue;}));System.out.println(dto1);//JSON字段特殊处理// 实体类包含JSON字符串UserEntity entity2 = new UserEntity();UserDTO dto2 = new UserDTO();entity2.setUserName(" 张三");entity2.setAge(25);entity2.setExtraJson("{\"permissions\":[\"read\",\"write\"]}");BeanUtil.copyProperties(entity2, dto2);System.out.println(dto2);if (StrUtil.isNotBlank(dto2.getExtraJson())) {dto2.setPermissions(JSONUtil.parseObj(dto2.getExtraJson()).get("permissions", List.class));}System.out.println(dto2);//忽略指定字段//跳过age字段复制UserEntity entity3 = new UserEntity();entity3.setUserName(" 张三");entity3.setAge(25);UserDTO dto3 = new UserDTO();BeanUtil.copyProperties(entity3, dto3,CopyOptions.create().setIgnoreProperties("age"));System.out.println(dto3);//深拷贝嵌套对象// 需要手动处理嵌套对象UserEntity userEntity4 = new UserEntity();userEntity4.setUserName("张三");Department department = new Department();department.setDeptCode("001");userEntity4.setDept(department);UserDTO dto4 = new UserDTO();BeanUtil.copyProperties(userEntity4, dto4);if (userEntity4.getDept() != null) {dto4.setDepartment(BeanUtil.copyProperties(userEntity4.getDept(), DeptDTO.class));}System.out.println(userEntity4);System.out.println(userEntity4);//copyToList 嵌套属性List<UserEntity> list = Arrays.asList(new UserEntity("李四", 30, new Department("001", "A")),new UserEntity("王五", 20, new Department("002", "B")));List<UserDTO> userDTOS = BeanUtil.copyToList(list, UserDTO.class);System.out.println(userDTOS);List<Department> departments = BeanUtil.copyToList(list, Department.class);System.out.println(departments);}
}
嵌套属性List复制示例
import cn.hutool.core.bean.BeanUtil;
import lombok.Data;import java.util.Arrays;
import java.util.List;public class HutoolsCopyNestCollectionUtilsDemo {// 嵌套实体类@Datapublic static class Department {private String deptCode;private String deptName;Department(String deptCode, String deptName){this.deptCode = deptCode;this.deptName = deptName;}}@Datapublic static class EmployeeEntity {private String empId;private Department department; // 嵌套对象EmployeeEntity(String empId, Department department){this.empId = empId;this.department = department;}}// DTO类@Datapublic static class EmployeeDTO {private String empId;private Department department; // 同名字段自动复制引用}public static void main(String[] args) {// 执行复制(注意:嵌套对象是引用拷贝)List<EmployeeEntity> entities = Arrays.asList(new EmployeeEntity("E1001", new Department("D001", "研发部")));List<EmployeeDTO> dtos = BeanUtil.copyToList(entities, EmployeeDTO.class);System.out.println(dtos);//[HutoolsCopyNestCollectionUtilsDemo.EmployeeDTO(empId=E1001, department=HutoolsCopyNestCollectionUtilsDemo.Department(deptCode=D001, deptName=研发部))]// 修改原嵌套对象会影响DTO中的值entities.get(0).getDepartment().setDeptName(" 测试部");System.out.println(dtos.get(0).getDepartment().getDeptName());// 输出"测试部"(说明是浅拷贝)}
}