拷贝对象 从apple 到orange
一、使用Function or BiFunction完成对象转换
适用场景:不约束a ,b对象的属性名称以及类型,可以根据业务需求手动转化
优点:更加灵活,eg:
字段名称不一致的对象之间也可以互转,所以更加灵活
缺点:
1 对于字段较多的对象之间相互转化,比较繁琐且易出错
2 扩展的时候,修改bean字段同时,还要对应修改convert类,操作繁琐
适用于字段较少的dto之间的转换。
1、引入类库
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2、测试类
将apple 对象赋值给orange对象:
/** 适用场景:
* 要转换一个对象的多个属性
* */
@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对象转换
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、转化类定义
/**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());
};
}
二、mapstruct
测试样例适用场景描述
1、被赋值前提是字段名一致,基本数据类型一致,如果是自定义bean类型,那bean里的字段基本类型以及名称要一致
2、测试mapStruct ,a 类 和b 类 不完全相同,从a拷贝到b , b里只是 跟a交叉的部分 会被赋值
3、测试得知:list<String>
,list<bean>
类型变量可以被赋值
**优点:**直接通过字段类型和名称进行匹配互转,扩展的时候,只需要修改基础bean就行 ,无需调整convert类。
**缺点:**遇到名称不匹配的字段,想要转换,需要单独适配。
适用于字段较多的dto之间的转换,当前前提还是字段名称要保持一致。
1 基本类型要一致
2 字段名称一致才能转
1、引入类库:
<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、测试类
/**
* 测试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接口声明,使用注解
定义转化类型
@Mapper
public interface MoreFieldConvert {
MoreFieldConvert convert= Mappers.getMapper(MoreFieldConvert.class);
/**
* 返回值必须要有空构造
* */
MoreFieldAC convertMoreFieldAC(MoreFieldABC moreFieldABC);
}
三、前置类:
将apple 对象赋值给orange对象
基础类
@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转化要用来测试的基础类
@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;
}
}