Java basics 2: Copy object method: from a to b

1. Use Function or BiFunction to complete object conversion

Applicable scenarios: There is no restriction on the attribute names and types of objects a and b. They can be converted manually according to business needs.
Advantages : more flexible, eg:
objects with inconsistent field names can also be converted to each other, so it is moreflexible
Disadvantages :
1. Converting objects with many fields to each other is cumbersome and error-prone.
2. When extending, when modifying bean fields, the convert class must also be modified accordingly, which is cumbersome operation.
Suitable for conversion between DTOs with fewer fields.

1. Introduce class library
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.70</version>
 </dependency>
2. Test category

Assign the apple object to the orange object:

 /** 适用场景:
   * 要转换一个对象的多个属性
   * */
    @Test
    public void testConvertObject(){
    
    
        Apple a=   new Apple("red", BigDecimal.valueOf(1.2));
        List<WareRanking>   wareRankLists=new ArrayList<>();
        for(int i=1;i<=3;i++){
    
    
            wareRankLists.add(new WareRanking("a"+i,i));
        }
        a.setWareRankLists(wareRankLists);
        Orange orange=AppleConvert.convertApple.apply(a);

        log.info("orange={}", JSON.toJSONString(orange));
    }
    结果:
    orange={
    
    "color":"red","wareRankLists":[{
    
    "detailRankingImage":"a1","rankingOrder":1},{
    
    "detailRankingImage":"a2","rankingOrder":2},{
    
    "detailRankingImage":"a3","rankingOrder":3}]
    ,"weight":1.2}

list object conversion

    List<Apple> list = new ArrayList<>();
	//数据准备
    @Before
    public void iniListData2() {
    
    
        Date curDate = new Date();
        Apple a = new Apple(1L, "red1", BigDecimal.valueOf(1.1d), DateUtils.addDays(curDate, 1));
        Apple b = new Apple(2L, "red2", BigDecimal.valueOf(1.2d), curDate);
        Apple c = new Apple(3L, "red3", BigDecimal.valueOf(1.3d), DateUtils.addDays(curDate, 2));
        list.add(a);
        list.add(b);
        list.add(c);
        List<WareRanking> wareRankLists=null;
        for(Apple aa :list ){
    
    
            wareRankLists=new ArrayList<>();
            for(int i=1;i<=3;i++){
    
    
                wareRankLists.add(new WareRanking("a",i));
            }
            aa.setWareRankLists(wareRankLists);
        }
    }
    /**
     * 适用场景:
     * list  泛型为对象,要转换对象的多个属性
     * */
    @Test
    public void testConvertList(){
    
    
        List<Orange> orangeList=AppleConvert.convertAppleList.apply(list);
        log.info("orangeList={}", JSON.toJSONString(orangeList));
    }
结果:
orangeList=[{
    
    "color":"red1","wareRankLists":[{
    
    "detailRankingImage":"a","rankingOrder":1},{
    
    "detailRankingImage":"a","rankingOrder":2},{
    
    "detailRankingImage":"a","rankingOrder":3}],"weight":1.1},{
    
    "color":"red2","wareRankLists":[{
    
    "detailRankingImage":"a","rankingOrder":1},{
    
    "detailRankingImage":"a","rankingOrder":2},{
    
    "detailRankingImage":"a","rankingOrder":3}],"weight":1.2},{
    
    "color":"red3","wareRankLists":[{
    
    "detailRankingImage":"a","rankingOrder":1},{
    
    "detailRankingImage":"a","rankingOrder":2},{
    
    "detailRankingImage":"a","rankingOrder":3}],"weight":1.3},
3. Conversion class definition
/**Description:苹果和橘子  互转 */
public class AppleConvert {
    
    

    public static Function<Apple, Orange> convertApple = apple -> {
    
    
        Orange orange = new Orange();
        orange.setColor(apple.getColor());
        orange.setWeight(apple.getWeight());
        orange.setWareRankLists(AppleConvert.convertAppleWareRankLists.apply(apple.getWareRankLists()));
        return orange;
    };

    public static Function<List<WareRanking>, List<SkuInfo>> convertAppleWareRankLists = source -> {
    
    
        source = CollectionUtils.isNotEmpty(source) ? source.stream().filter(Objects::nonNull).collect(Collectors.toList()) : new ArrayList<>();
        if (CollectionUtils.isEmpty(source)) {
    
    
            return null;
        }
        List<SkuInfo> target = source.stream().map(wareRanking -> {
    
    
            return new SkuInfo(wareRanking.getDetailRankingImage(), wareRanking.getRankingOrder());
        }).collect(Collectors.toList());

        return target;
    };
    public static Function<List<Apple>, List<Orange>> convertAppleList = appleList -> {
    
    
        if (CollectionUtils.isEmpty(appleList)) {
    
    
            return null;
        }
        return appleList.stream().map(apple -> {
    
    
            Orange orange = new Orange();
            orange.setColor(apple.getColor());
            orange.setWeight(apple.getWeight());
            orange.setWareRankLists(AppleConvert.convertAppleWareRankLists.apply(apple.getWareRankLists()));
            return orange;
        }).collect(Collectors.toList());
    };
}

2. mapstruct

Test sample applicable scenario description

1. The prerequisite for assignment is that the field names and basic data types are consistent. If it is a custom bean type, the basic types and names of the fields in the bean must be consistent. 2.
Test mapStruct, class a and class b are not exactly the same, copy from a to b, only the part in b that intersects with a will be assigned.
3. The test shows: list<String>, list<bean>type variables can be assigned.

**Advantages:** Match and convert directly through field types and names. When extending, you only need to modify the basic bean without adjusting the convert class.
**Disadvantages:** If you encounter fields with mismatched names and want to convert them, you need to adapt them separately.
It is suitable for conversion between DTOs with many fields. The current prerequisite is that the field names must be consistent.

1. The basic types must be consistent.
2. The field names must be consistent before conversion can be performed.

1. Introduce the class library:
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct</artifactId>
	<version>1.2.0.Final</version>
</dependency>

<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-processor</artifactId>
	<version>1.2.0.Final</version>
	<scope>provided</scope>
</dependency>
2. Test category
 /**
     * 测试mapStruct  ,a 类 和b 类 不完全相同,从a拷贝到b   ,b里只是  跟a交叉的部分
     * */
   @Test
    public void testMapStruct() {
    
    
        MoreFieldABC abc = new MoreFieldABC("name1", 2, "abc3");

        //普通类型的   list  也可以互转
        List<String> listAbc = new ArrayList<String>();
        listAbc.add("1");
        listAbc.add("2");
        listAbc.add("3");
        abc.setStrList(listAbc);

        //组装类型的bean  的  list  也可以互转
        List<Apple> appleList = new ArrayList<Apple>();
        for (int i = 0; i < 3; i++) {
    
    
            Apple a=new Apple("red"+i, BigDecimal.valueOf(1.5+i));
            appleList.add(a);
        }
        abc.setAppleList(appleList);

        MoreFieldAC ac = MoreFieldConvert.convert.convertMoreFieldAC(abc);
        log.info("ac={}", JSON.toJSONString(ac));
    }
结果
ac={
    
    
"id":2,"name":"name1",
"appleList":[{
    
    "color":"red0","weight":1.5},{
    
    "color":"red1","weight":2.5},{
    
    "color":"red2","weight":3.5}],
"strList":["1","2","3"]}
3. Convert interface declaration, using annotations

Define conversion type

@Mapper
public interface MoreFieldConvert {
    
    
    MoreFieldConvert convert= Mappers.getMapper(MoreFieldConvert.class);
    /**
     * 返回值必须要有空构造
     * */
    MoreFieldAC convertMoreFieldAC(MoreFieldABC moreFieldABC);
}

3. Pre-category:

Assign the apple object to the orange object

Basic class

@Data
public class Apple {
    
    
    private Long id;
    private Date modifyTime;
    private String color;
    private BigDecimal weight=BigDecimal.TEN;
    private WareRanking wareRanking;
    private List<WareRanking> wareRankLists;
    /**
     * 序号
     */
    private Integer sortNo;

    public Apple(String color, BigDecimal weight,Date modifyTime) {
    
    
        this.color = color;
        this.weight = weight;
        this.modifyTime=modifyTime;
    }
    public Apple(Long id,String color, BigDecimal weight,Date modifyTime) {
    
    
        this.color = color;
        this.weight = weight;
        this.modifyTime=modifyTime;
        this.id=id;
    }
    public Apple(String color, BigDecimal weight) {
    
    
        this.color = color;
        this.weight = weight;
    }
    public Apple(String color) {
    
    
        this.color = color;
    }
    public Apple( ) {
    
    

    }

    public Apple getApple(String color, BigDecimal weight){
    
    
        if(color.equals(this.color) && weight==this.weight){
    
    
            return this;
        }

        return null;
    }
}

@AllArgsConstructor
@NoArgsConstructor
@Data
public class WareRanking {
    
    
    /**
     * 图标
     */
    private String detailRankingImage;
    /**
     * 排行榜顺序
     */
    private Integer rankingOrder;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Orange {
    
    

    private String color;
    private BigDecimal weight;
    private List<SkuInfo> wareRankLists;

    public Orange(String color, BigDecimal weight) {
    
    
        this.color = color;
        this.weight = weight;
    }
}
@AllArgsConstructor
@NoArgsConstructor
@Data
public class SkuInfo {
    
    
    /**
     * 图标
     */
    private String detailRankingImage;
    /**
     * 排行榜顺序
     */
    private Integer rankingOrder;

}

@mapper transforms the base class to be used for testing

@Data
public class MoreFieldABC {
    
    
    private String name;
    private int id;
    // private Date birth;
    private String abc;
    private List<String> strList;
    private List<Apple> appleList;

    public MoreFieldABC(String name, int id, String abc) {
    
    
        this.name = name;
        this.id = id;
        this.abc = abc;
    }
}
@Data
public class MoreFieldAC {
    
    
    private String name;
    private int id;
    private List<String> aList;
    private List<String> strList;
   private List<Apple> appleList;
  //private List<Orange> AppleList;  即便类型不一样,但是变量名称一样,且类型bean 里得属性都一样,也可以拷贝成功
  //private List<Orange> orangeList;  //属性名称,属性类型都不一样,不能拷贝赋值到这里
    private String eee;
    public MoreFieldAC() {
    
    
    }
    public MoreFieldAC(String name, int id, String eee) {
    
    
        this.name = name;
        this.id = id;
        this.eee = eee;
    }
} 

Supongo que te gusta

Origin blog.csdn.net/qq_17033579/article/details/108963304
Recomendado
Clasificación