1. Overview
1.概述
In this tutorial, we’ll explain how to map lists of different element types using the ModelMapper framework. This involves using generic types in Java as a solution to convert different types of data from one list to another.
在本教程中,我们将介绍如何使用ModelMapper框架来映射不同元素类型的列表。T这涉及到在Java中使用泛型作为将不同类型的数据从一个列表转换成另一个列表的解决方案。
2. Model Mapper
2.模型映射器
The main role of ModelMapper is to map objects by determining how one object model is mapped to another called a Data Transformation Object (DTO).
ModelMapper的主要作用是通过确定一个对象模型如何映射到另一个称为数据转换对象(DTO)的对象。
In order to use ModelMapper, we start by adding the dependency to our pom.xml:
为了使用ModelMapper,我们首先要将该依赖关系添加到我们的pom.xml。
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.7</version>
</dependency>
2.1. Configuration
2.1.配置
ModelMapper provides a variety of configurations to simplify the mapping process. We customize the configuration by enabling or disabling the appropriate properties in the configuration. It’s a common practice to set the fieldMatchingEnabled property to true and allow private field matching:
ModelMapper提供各种配置以简化映射过程。我们通过启用或禁用配置中的适当属性来定制配置。将fieldMatchingEnabled属性设置为true并允许私有字段匹配:这是一个常见做法。
By doing so, ModelMapper can compare private fields in the mapping classes (objects). In this configuration, it’s not strictly necessary that all fields with the same names exist in both classes. Several Matching Strategies are allowed. By default, a standard matching strategy requires that all source and destination properties must be matched in any order. This is ideal for our scenario.
通过这样做,ModelMapper可以比较映射类(对象)中的私有字段。在这种配置中,并不严格要求所有具有相同名称的字段都存在于两个类中。允许几个匹配策略。默认情况下,标准匹配策略要求所有源和目标属性必须以任何顺序进行匹配。这对于我们的方案来说是很理想的.。
2.2. Type Token
2.2.类型令牌
ModelMapper uses TypeToken to map generic types. To see why this is necessary, let’s see what happens when we map an Integer list to a Character list:
ModelMapper 使用 TypeToken来映射通用类型。为了了解为什么这是有必要的,让我们看看当我们将一个Integer列表映射到一个Character列表时会发生什么:。
List<Integer> integers = new ArrayList<Integer>();
integers.add(1);
integers.add(2);
integers.add(3);
List<Character> characters = new ArrayList<Character>();
modelMapper.map(integers, characters);
Further, if we print out the elements of the characters list we would see an empty list. This is due to the occurrence of type erasure during runtime execution.
此外,如果我们打印出characters列表中的元素,我们会看到一个空列表。这是由于在运行时执行过程中发生了类型擦除。
If we change our map call to use TypeToken, though, we can create a type literal for List<Character>:
如果我们改变我们的map调用,使用TypeToken,但我们可以为List<Character>:
List<Character> characters
= modelMapper.map(integers, new TypeToken<List<Character>>() {}.getType());
At compile time, the TokenType anonymous inner case preserves the List<Character> parameter type, and this time our conversion is successful.
在编译时,TokenType 匿名内例保留了List<Character>参数类型,这一次我们的转换成功了。
3. Using Custom Type Mapping
3.使用自定义类型映射
Lists in Java can be mapped using custom element types.
Java中的列表可以使用自定义元素类型进行映射。
For example, let’s say we want to map a list of User entities to a UserDTO list. To achieve this, we’ll call map for each element:
例如,假设我们想把一个User实体的列表映射到一个UserDTO列表。为了实现这个目标,我们将为每个元素调用map:。
List<UserDTO> dtos = users
.stream()
.map(user -> modelMapper.map(user, UserDTO.class))
.collect(Collectors.toList());
Of course, with some more work, we could make a general-purpose parameterized method:
当然,如果再做一些工作,我们可以制作一个通用的参数化方法:
<S, T> List<T> mapList(List<S> source, Class<T> targetClass) {
return source
.stream()
.map(element -> modelMapper.map(element, targetClass))
.collect(Collectors.toList());
}
So, then, we could instead do:
那么,我们可以改为做。
List<UserDTO> userDtoList = mapList(users, UserDTO.class);
4. Type Map and Property Mapping
4.类型图和属性图
Specific properties such as lists or sets can be added to the User-UserDTO model. TypeMap provides a method for explicitly defining the mapping of these properties. The TypeMap object stores mapping information of specific types (classes):
特定的属性(如列表或集合)可以被添加到User-UserDTO模型中。TypeMap提供了一种明确定义这些属性的映射的方法。TypeMap对象存储特定类型(类)的映射信息:
TypeMap<UserList, UserListDTO> typeMap = modelMapper.createTypeMap(UserList.class, UserListDTO.class);
UserList class contains a collection of Users. Here, we want to map the list of usernames from this collection to the property list of the UserListDTO class. To achieve this, we will create first UsersListConverter class and pass it List <User> and List <String> as parameter types for conversion:
UserList类包含一个Users的集合。在这里,we想要将这个集合中的用户名列表映射到UserListDTO类的属性列表。为了实现这个目标,我们将首先创建UsersListConverter类,并将List <User>和List <String> 作为转换的参数类型:
public class UsersListConverter extends AbstractConverter<List<User>, List<String>> {
@Override
protected List<String> convert(List<User> users) {
return users
.stream()
.map(User::getUsername)
.collect(Collectors.toList());
}
}
From the created TypeMap object we explicitly add Property Mapping by invoking an instance of UsersListConverter class:
从创建的TypeMap对象中,我们明确添加属性映射通过调用UsersListConverter类实例:
typeMap.addMappings(mapper -> mapper.using(new UsersListConverter())
.map(UserList::getUsers, UserListDTO::setUsernames));
Inside the addMappings method, an expression mapping allows us to define the source to destination properties with lambda expressions. Finally, it converts the list of users into the resulting list of usernames.
在addMappings方法中,表达式映射允许我们用lambda表达式定义源到目的属性。最后,它将用户列表转换为结果的用户名列表。
5. Conclusion
5.总结
In this tutorial, we explained how lists are mapped by manipulating generic types in ModelMapper. We can make use of TypeToken, generic type mapping, and property mapping to create object list types and make complex mappings.
在本教程中,我们解释了如何通过在 ModelMapper中操作通用类型来映射列表。我们可以利用TypeToken、通用类型映射和属性映射来创建对象列表类型并进行复杂映射。
The complete source code for this article is available over on GitHub.
本文的完整源代码可在GitHub上获得,。