Java使用Streams API不修改原类前提下映射指定字段到目标类对象
解决方案
以下是几种符合「不能修改A、B类」要求的优化方案,可根据你的业务场景选择:
方案1:基于函数式接口封装通用转换逻辑(无额外依赖,性能最优)
适合有多个不同字段映射场景的需求,不用为每一种实体转换写单独的转换方法,灵活度极高,全程无反射开销,性能和手写赋值一致。
首先封装通用列表转换工具:
import java.util.List; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.Collectors; public class CommonConverter { /** * 通用列表转换方法 * @param sourceList 源对象列表 * @param targetSupplier 目标对象实例化逻辑 * @param mapper 源到目标的字段赋值逻辑 * @return 转换后的目标对象列表 */ public static <S, T> List<T> convertList(List<S> sourceList, Supplier<T> targetSupplier, BiConsumer<S, T> mapper) { return sourceList.stream() .map(source -> { T target = targetSupplier.get(); mapper.accept(source, target); return target; }) .collect(Collectors.toList()); } }
使用示例:
- 仅映射name字段的场景:
List<A> aList = new ArrayList<>(); List<B> bList = CommonConverter.convertList(aList, B::new, (a, b) -> b.setName(a.getName()));
- 多字段映射场景(后续扩展无需修改工具类):
List<B> bList = CommonConverter.convertList(aList, B::new, (a, b) -> { b.setName(a.getName()); // 按需添加其他字段赋值逻辑即可 });
方案2:使用Bean映射框架(适合大量实体映射场景,降低维护成本)
如果你的项目中有大量类似的实体转换需求,可以使用成熟的映射框架,避免手动写重复的赋值逻辑:
推荐:MapStruct(编译期生成代码,无反射开销,性能和手写一致)
只需要定义映射接口,框架会自动生成实现代码:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper public interface ABMapper { ABMapper INSTANCE = Mappers.getMapper(ABMapper.class); // 忽略不需要赋值的country字段,自动匹配同名的name字段 @Mapping(target = "country", ignore = true) B aToB(A a); }
转换列表的代码:
List<B> bList = aList.stream() .map(ABMapper.INSTANCE::aToB) .collect(Collectors.toList());
轻量方案:Spring BeanUtils(基于反射,适合简单场景)
如果项目已经依赖Spring框架,不需要额外引入其他依赖即可使用:
import org.springframework.beans.BeanUtils; List<B> bList = aList.stream() .map(a -> { B b = new B(); // 第三个参数为需要忽略的字段,这里忽略country,只赋值匹配的name字段 BeanUtils.copyProperties(a, b, "country"); return b; }) .collect(Collectors.toList());
注意:不推荐使用Apache Commons的BeanUtils,性能远低于Spring版本。
方案3:简化现有写法
如果不想调整现有结构,可直接用方法引用简化原有代码,逻辑完全不变:
private List<B> mapAtoB(List<A> aList) { return aList.stream().map(this::mapToB).collect(Collectors.toList()); } private B mapToB(A a) { B b = new B(); b.setName(a.getName()); return b; }
内容的提问来源于stack exchange,提问作者Jagadesh
相关产品推荐
相关产品推荐

