You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mapstruct将扁平化父子列表映射为嵌套父子结构?

使用Mapstruct实现扁平化列表到嵌套父子结构的映射

核心思路

Mapstruct擅长单对象的属性映射,但父子归组逻辑需要结合Java Stream的分组能力。我们可以先定义基础的单对象映射规则,再通过自定义方法完成分组和子列表的归集工作。

步骤1:定义Mapstruct映射接口

创建Mapper接口,分别实现Flattened到Parent、Flattened到Child的单对象映射,同时忽略Parent的children字段(后续手动处理):

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Mapper(componentModel = "spring") // Spring环境用此配置,非Spring环境用default
public interface FlattenedMapper {
    FlattenedMapper INSTANCE = Mappers.getMapper(FlattenedMapper.class);

    // 映射Flattened的父属性到Parent,忽略children字段
    @Mapping(target = "children", ignore = true)
    Parent toParent(Flattened flattened);

    // 映射Flattened的子属性到Child
    Child toChild(Flattened flattened);

    // 核心方法:处理列表分组与子对象归集
    default List<Parent> map(List<Flattened> flattenedList) {
        // 按parentId对扁平化列表分组
        Map<Integer, List<Flattened>> groupedByParentId = flattenedList.stream()
                .collect(Collectors.groupingBy(Flattened::getParentId));

        // 遍历分组,生成嵌套结构的Parent列表
        return groupedByParentId.entrySet().stream()
                .map(entry -> {
                    List<Flattened> group = entry.getValue();
                    // 取分组内第一个对象映射父属性(假设同parentId的父属性完全一致)
                    Parent parent = toParent(group.get(0));
                    // 将分组内所有对象映射为Child并归集到Parent的children
                    List<Child> children = group.stream()
                            .map(this::toChild)
                            .collect(Collectors.toList());
                    parent.setChildren(children);
                    return parent;
                })
                .collect(Collectors.toList());
    }
}

关键细节说明

  • 假设同一parentId对应的所有Flattened对象的父属性(someParentProperty1等)完全一致,因此取分组内第一个对象映射父属性即可。如果存在属性不一致的场景,需要额外添加属性合并的逻辑。
  • 若使用Spring框架,@Mapper的componentModel设为spring后,可直接通过依赖注入使用Mapper;非Spring环境用default,通过INSTANCE静态调用即可。
  • Mapstruct会自动生成toParent和toChild的属性映射实现,无需手动编写重复的赋值代码。

使用示例

// 测试代码示例
List<Flattened> flattenedList = Arrays.asList(
        new Flattened(1, 101, "父属性A", "子属性101"),
        new Flattened(1, 102, "父属性A", "子属性102"),
        new Flattened(2, 201, "父属性B", "子属性201")
);

List<Parent> parents = FlattenedMapper.INSTANCE.map(flattenedList);
// 结果:2个Parent对象,第一个Parent包含2个Child,第二个包含1个Child

内容的提问来源于stack exchange,提问作者gzak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 12:29:56