Why MapStruct Is the Fastest Java Bean Mapper and How to Use It
This article introduces MapStruct, a compile‑time Java bean‑mapping framework, explains why it outperforms other mappers, shows how to configure Maven, define mapper interfaces, handle custom field mappings, and demonstrates its impressive runtime performance with practical code examples.
Why Use MapStruct?
In layered software architectures, different layers often use distinct data models such as DO, DTO, and VO, requiring frequent object‑to‑object conversion. Writing manual getter/setter mappings is verbose and error‑prone, which is why developers look for automatic mapping tools.
Using MapStruct
MapStruct (https://mapstruct.org/) is a compile‑time code generator that creates type‑safe, fast mapping implementations based on the "convention over configuration" principle.
Convention over configuration, also known as programming by convention, reduces the number of decisions developers must make while retaining flexibility.
Assume we have two classes that need conversion:
<code>public class PersonDO {
private Integer id;
private String name;
private int age;
private Date birthday;
private String gender;
}
public class PersonDTO {
private String userName;
private Integer age;
private Date birthday;
private Gender gender;
}</code>First, add the MapStruct dependency and configure the Maven compiler plugin to use the MapStruct processor:
<code><properties>
<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build></code>Define a mapper interface:
<code>@Mapper
public interface PersonConverter {
PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
@Mappings({
@Mapping(source = "name", target = "userName")
})
PersonDTO do2dto(PersonDO person);
}</code>Test the mapper:
<code>public static void main(String[] args) {
PersonDO personDO = new PersonDO();
personDO.setName("Hollis");
personDO.setAge(26);
personDO.setBirthday(new Date());
personDO.setId(1);
personDO.setGender(Gender.MALE.name());
PersonDTO personDTO = PersonConverter.INSTANCE.do2dto(personDO);
System.out.println(personDTO);
}</code>The output shows that the fields are correctly mapped:
<code>PersonDTO{userName='Hollis', age=26, birthday=Sat Aug 08 00:00:44 CST 2020, gender=MALE}</code>Handling Special Mappings
If source and target property names differ, use
@Mapping(source = "name", target = "userName"). MapStruct can also map differing types automatically for primitives, their wrappers,
String, and enums.
For constant values, use the
constantattribute:
<code>@Mapping(source = "name", constant = "hollis")</code>When a field requires custom conversion (e.g., a
Stringaddress to a
HomeAddressobject), define a default method in the mapper and reference it with an expression:
<code>@Mapping(target = "address", expression = "java(homeAddressToString(dto.getAddress()))")
default String homeAddressToString(HomeAddress address) {
return JSON.toJSONString(address);
}</code>MapStruct also supports built‑in date formatting:
<code>@Mapping(target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")</code>Performance
Benchmarking shows that mapping 1,000; 10,000; 100,000; and 1,000,000 objects takes 0 ms, 1 ms, 3 ms, and 6 ms respectively, far faster than many alternative libraries.
The speed comes from compile‑time generation of plain Java code, eliminating reflection and allowing the JVM to inline the mapping logic. Errors are also caught at compile time, forcing developers to fix mapping issues early.
Conclusion
MapStruct is a lightweight, compile‑time Java bean‑mapping framework that dramatically reduces boilerplate, handles complex field conversions, and delivers near‑zero runtime overhead. It is especially useful in backend services where DTO‑DO‑VO conversions are frequent.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.