商城首页欢迎来到中国正版软件门户

您的位置:首页 >根据对象字段对列表进行分组并生成嵌套列表,是数据处理中常见的操作。在 Python 中,可以使用 itertools.groupby() 或者手动遍历实现。以下

根据对象字段对列表进行分组并生成嵌套列表,是数据处理中常见的操作。在 Python 中,可以使用 itertools.groupby() 或者手动遍历实现。以下

  发布于2026-02-11 阅读(0)

扫一扫,手机访问

如何根据对象字段对列表进行分组并生成嵌套列表

本文介绍如何基于 Java 8 Stream API 和 Collectors.groupingBy,按对象的指定字段(如 shape、size 或二者组合)将 List 动态分组为 List>,适用于多策略分组场景。

在实际开发中,常需根据业务类型(如 "type_1"、"type_2")对同一对象列表执行不同维度的分组逻辑:仅按 shape、仅按 size,或联合按 shape 和 size。核心目标是将原始 List<Obj> 转换为 List<List<Obj>> —— 即每个子列表包含字段值相同的对象。

✅ 基础分组:按单个字段(如 shape)

使用 Collectors.groupingBy(Obj::getShape) 可将对象按 shape 分组为 Map<String, List<Obj>>,再提取其 values() 并转为 ArrayList 即可:

public List<List<Obj>> groupByShape(List<Obj> objs) {
    return new ArrayList<>(objs.stream()
        .collect(Collectors.groupingBy(Obj::getShape))
        .values());
}

⚠️ 注意:请确保 Obj 类已提供 getShape()(及 getSize())等标准 getter 方法;若字段为 private,直接访问 obj.shape 在 lambda 中不可行。

✅ 进阶分组:按多个字段(如 shape + size)

联合分组需构造唯一键。推荐使用 AbstractMap.SimpleEntry 或自定义键类,但最简洁安全的方式是用 Record(Java 14+)或匿名对象(Java 17+),或拼接字符串(需确保无歧义):

// 方式1:使用 record(推荐,类型安全、可读性高)
public List<List<Obj>> groupByShapeAndSize(List<Obj> objs) {
    return new ArrayList<>(objs.stream()
        .collect(Collectors.groupingBy(
            obj -> new AbstractMap.SimpleImmutableEntry<>(obj.getShape(), obj.getSize())
        ))
        .values());
}

// 方式2:字符串拼接(兼容低版本,但需注意转义,如 shape="a_b", size="c_d" 可能冲突)
public List<List<Obj>> groupByShapeAndSizeSafe(List<Obj> objs) {
    return new ArrayList<>(objs.stream()
        .collect(Collectors.groupingBy(
            obj -> obj.getShape() + "\0" + obj.getSize() // 使用不可见分隔符 \0 更安全
        ))
        .values());
}

✅ 统一调度:在 functionName 中集成策略

将分组逻辑封装为函数式接口,使主流程清晰可维护:

public void functionName(Map<String, List<Obj>> objMap) {
    Map<String, Function<List<Obj>, List<List<Obj>>>> strategies = Map.of(
        "type_1", this::groupByShape,
        "type_2", this::groupBySize,
        "type_3", this::groupByShapeAndSize
    );

    objMap.forEach((type, objs) -> {
        Function<List<Obj>, List<List<Obj>>> strategy = strategies.get(type);
        if (strategy != null) {
            List<List<Obj>> grouped = strategy.apply(objs);
            // ✅ 此处执行后续处理:如统计、聚合、持久化等
            processGroupedResults(grouped);
        }
    });
}

private void processGroupedResults(List<List<Obj>> grouped) {
    for (int i = 0; i < grouped.size(); i++) {
        System.out.println("Group " + (i + 1) + ": " + grouped.get(i).size() + " objects");
        // e.g., grouped.get(i) is a List<Obj> with same shape/size
    }
}

? 验证示例输出

以输入:

{
  "key": "type_3",
  "value": [
    {"size":"m1","shape":"s1","name":"Obj_1"},
    {"size":"m2","shape":"s1","name":"Obj_2"},
    {"size":"m1","shape":"s1","name":"Obj_3"}
  ]
}

调用 groupByShapeAndSize() 后,将生成:

  • [(s1,m1) → [Obj_1, Obj_3]]
  • [(s1,m2) → [Obj_2]]
    → 最终 List<List<Obj>> 包含两个子列表,完全符合预期。

✅ 总结

  • 使用 Collectors.groupingBy 是实现动态分组的最简高效方案;
  • 单字段分组直接传方法引用(如 Obj::getShape);
  • 多字段分组优先使用 SimpleImmutableEntry 或 record 构建复合键,避免字符串拼接风险;
  • 将分组策略与主逻辑解耦(如 Map<String, Function>),提升可扩展性与可测试性;
  • 所有分组结果均为内存内 List<List<Obj>>,无需额外依赖,开箱即用。
本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注