如何通过Mapstruct优雅实现B类到C类的Stack转换并保序?
用Mapstruct优雅实现B到C的对象转换(保持Stack顺序一致)
当然可以用Mapstruct轻松搞定这个需求!而且能做到代码简洁、维护性强,完全符合你想要的“优雅方案”。下面我会一步步给你演示具体实现:
核心思路
Mapstruct本身支持集合类型的转换,但因为Stack是具有后进先出特性的特殊集合,直接用默认的集合转换会导致元素顺序反转(默认按迭代器顺序处理,而Stack的迭代器是从栈底到栈顶遍历)。所以我们需要自定义一个Stack的转换逻辑,保证转换后的Stack元素弹出顺序和原Stack完全一致。
具体实现步骤
1. 定义Mapstruct转换器接口
首先创建一个Mapper接口,指定组件模型(比如spring或者default,根据你的项目环境选择),然后定义三个关键方法:
- 单个
A对象转Long(提取id字段) - 自定义
Stack<A>转Stack<Long>的方法(保证顺序) - 主转换方法:
B转C
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import java.util.Stack; @Mapper(componentModel = "spring") // 如果是Spring项目用这个,否则用componentModel="default" public interface BToCMapper { // 实例化转换器(非Spring环境用这个方式获取实例) BToCMapper INSTANCE = Mappers.getMapper(BToCMapper.class); // 单个A转Long:提取id字段 default Long mapAToLong(A a) { return a != null ? a.getId() : null; } // 自定义Stack转换逻辑:保证顺序一致 default Stack<Long> mapStackAToStackLong(Stack<A> sourceStack) { if (sourceStack == null) { return null; } Stack<Long> targetStack = new Stack<>(); // 用临时栈中转,避免修改原Stack的内容 Stack<A> tempStack = new Stack<>(); // 先把原栈元素弹出到临时栈 while (!sourceStack.isEmpty()) { tempStack.push(sourceStack.pop()); } // 再从临时栈弹出,转换后push到目标栈,同时还原原栈 while (!tempStack.isEmpty()) { A a = tempStack.pop(); targetStack.push(mapAToLong(a)); sourceStack.push(a); } return targetStack; } // 主转换方法:映射myField字段 @Mapping(source = "myField", target = "myField") C convertBToC(B b); }
2. 使用转换器
在你的业务代码里,直接调用转换器的实例即可完成转换:
// 假设你已经有一个B类对象b B b = new B(); // 填充b的myField数据... // 转换为C类对象 C c = BToCMapper.INSTANCE.convertBToC(b);
关键细节说明
- 顺序一致性保证:通过临时栈中转的方式,我们确保了目标Stack的弹出顺序和原Stack完全一致——原栈最后push的元素,转换后依然是目标栈的栈顶元素。
- 原栈保护:代码中还原了原Stack的内容,避免转换操作修改原对象的状态(如果不需要保留原栈,可以去掉还原的步骤,简化代码)。
- 空值处理:添加了空值判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者Serge Harnyk
相关产品推荐
相关产品推荐

