我有两个相同类型的对象。所有字段都是
Map<String, SomeType>
,因此对象看起来像:
class Obj {
Map<String, TypeA> propA;
Map<String, TypeB> propB;
...
Obj setPropA(Map<String, TypeA> newMap) { ... }
Obj setPropB(Map<String, TypeB> newMap) { ... }
...
Obj putPropA(String key, TypeA a) { ... }
Obj putPropB(String key, TypeB b) { ... }
...
}
我需要通过合并/连接所有映射条目来合并其中两个对象(字符串键永远不会冲突)。目前,这是手工完成的。但是,这看起来很笨拙,并且在生成类时,一旦添加属性,合并就不完整。
Obj merge(Obj ob1, Obj ob2) {
return new Obj()
.setPropA(mergeMaps(ob1.getPropA(), ob2.getPropA()))
.setPropB(mergeMaps(ob1.getPropB(), ob2.getPropB()))
...;
}
<T> Map<String, T> mergeMaps(Map<String, T> aMap, Map<String, T> bMap) {
aMap.putAll(bMap);
return aMap;
}
可以使用mapstruct自动合并所有字段映射吗?
@Mapper
public interface ObjMapper {
ObjMapper INSTANCE = Mappers.getMapper(ObjMapper.class);
Obj merge(Obj source, @MappingTarget Obj target);
default <T> void mergeMaps(Map<String, T> source, @MappingTarget Map<String, T> target) {
if ( source == null ) {
return;
}
if ( target == null ) {
target = new HashMap<>();
}
target.putAll(source);
}
}
生成的代码是:
public class ObjMapperImpl implements ObjMapper {
@Override
public Obj merge(Obj source, Obj target) {
if ( source == null ) {
return target;
}
if ( source.getPropA() != null ) {
if ( target.getPropA() == null ) {
target.setPropA( new LinkedHashMap<String, ChildA>() );
}
mergeMaps( source.getPropA(), target.getPropA() );
}
else {
target.setPropA( null );
}
if ( source.getPropB() != null ) {
if ( target.getPropB() == null ) {
target.setPropB( new LinkedHashMap<String, ChildB>() );
}
mergeMaps( source.getPropB(), target.getPropB() );
}
else {
target.setPropB( null );
}
return target;
}
}
唯一的区别是它对目标进行了更新。 如果需要有一个新的对象,则需要执行两次merge方法:
Obj newObj = new Obj();
newObj = ObjMapper.INSTANCE.merge(ob1, newObj); // add from ob1
newObj = ObjMapper.INSTANCE.merge(ob2, newObj); // add from ob2