Copie objetos de maçã para laranja
1. Use Function ou BiFunction para concluir a conversão do objeto
Cenários aplicáveis: Não há restrição quanto aos nomes de atributos e tipos de objetos a e b. Eles podem ser convertidos manualmente de acordo com as necessidades do negócio. Vantagens:
mais flexíveis, por exemplo:
objetos com nomes de campos inconsistentes também podem ser convertidos entre si, portanto é maisflexível
Desvantagens :
1. Converter objetos com muitos campos entre si é complicado e sujeito a erros.
2. Ao estender, ao modificar campos de bean, a classe de conversão também deve ser modificada de acordo, o que é uma operação complicada.
Adequado para conversão entre DTOs com menos campos.
1. Apresente a biblioteca de classes
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2. Categoria de teste
Atribua o objeto maçã ao objeto laranja:
/** 适用场景:
* 要转换一个对象的多个属性
* */
@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}
listar conversão de objeto
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. Definição de classe de conversão
/**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. estrutura do mapa
Descrição do cenário aplicável da amostra de teste
1. O pré-requisito para atribuição é que os nomes dos campos e os tipos de dados básicos sejam consistentes. Se for um tipo de bean customizado, os tipos básicos e os nomes dos campos no bean devem ser consistentes. 2. Teste mapStruct, classe a e
classe b não são exatamente iguais, copie de a para b, apenas a parte em b que cruza com a será atribuída.
3. O teste mostra:list<String>
,list<bean>
variáveis de tipo podem ser atribuídas.
**Vantagens:** Combine e converta diretamente por meio de tipos e nomes de campos. Ao estender, você só precisa modificar o bean básico sem ajustar a classe de conversão.
**Desvantagens:** Se você encontrar campos com nomes incompatíveis e quiser convertê-los, será necessário adaptá-los separadamente.
É adequado para conversão entre DTOs com muitos campos. O pré-requisito atual é que os nomes dos campos sejam consistentes.
1. Os tipos básicos devem ser consistentes
2. Os nomes dos campos devem ser consistentes antes que a conversão possa ser executada.
1. Apresente a biblioteca de classes:
<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. Categoria de teste
/**
* 测试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. Converta a declaração da interface usando anotações
Definir tipo de conversão
@Mapper
public interface MoreFieldConvert {
MoreFieldConvert convert= Mappers.getMapper(MoreFieldConvert.class);
/**
* 返回值必须要有空构造
* */
MoreFieldAC convertMoreFieldAC(MoreFieldABC moreFieldABC);
}
3. Pré-categoria:
Atribua o objeto maçã ao objeto laranja
Aula básica
@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 converte a classe base a ser usada para teste
@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;
}
}