首页 > Java > java教程 > 正文

Java Stream API:高效实现数据分组与嵌套JSON列表转换

心靈之曲
发布: 2025-09-13 10:26:38
原创
529人浏览过

Java Stream API:高效实现数据分组与嵌套JSON列表转换

本文详细介绍了如何利用Java Stream API,特别是groupingBy和mapping收集器,将扁平化的数据列表(如数据库查询结果)根据某个字段进行分组,并将其关联数据聚合为一个嵌套的JSON列表结构。通过定义清晰的数据模型和分步实现,展示了将原始数据转换为更具层次感的结构化输出的专业方法。

在现代数据处理中,将扁平化的数据结构(例如,从数据库查询获得的列表)转换为更具层次感的聚合形式是一种常见需求。这在构建复杂的api响应、生成报表或处理业务逻辑时尤为重要。java 8引入的stream api提供了一套强大而简洁的工具,能够高效地完成此类数据转换任务。本教程将详细阐述如何利用stream api实现按指定字段分组,并将相关数据聚合成嵌套列表的场景。

1. 定义数据模型

为了清晰地表示原始数据和目标聚合数据,我们需要定义相应的Java类。

原始响应接口 (Response): 代表从数据源(如SQL查询)获取的每一条记录。

public interface Response {
    Long getId();
    String getSData();
    String getSName();
}
登录后复制

为了方便演示和代码运行,我们可以创建一个实现类:

// Response接口的实现类,用于模拟数据
public class ResponseImpl implements Response {
    private Long id;
    private String sData;
    private String sName;

    public ResponseImpl(Long id, String sData, String sName) {
        this.id = id;
        this.sData = sData;
        this.sName = sName;
    }

    @Override
    public Long getId() { return id; }
    @Override
    public String getSData() { return sData; }
    @Override
    public String getSName() { return sName; }

    @Override
    public String toString() {
        return "ResponseImpl{" +
               "id=" + id +
               ", sData='" + sData + '\'' +
               ", sName='" + sName + '\'' +
               '}';
    }
}
登录后复制

子数据类 (SubData): 代表分组后每个ID下的子列表中的元素。它包含了sData和sName字段。

立即学习Java免费学习笔记(深入)”;

public class SubData {
    private String sData;
    private String sName;

    public SubData(String sData, String sName) {
        this.sData = sData;
        this.sName = sName;
    }

    public String getSData() { return sData; }
    public String getSName() { return sName; }

    @Override
    public String toString() {
        return "SubData{" +
               "sData='" + sData + '\'' +
               ", sName='" + sName + '\'' +
               '}';
    }
}
登录后复制

新响应类 (NewResponse): 代表最终聚合后的结构,包含一个分组ID和其对应的SubData对象列表。

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 30
查看详情 Find JSON Path Online
import java.util.List;

public class NewResponse {
    private Long id;
    private List<SubData> subDataList;

    public NewResponse(Long id, List<SubData> subDataList) {
        this.id = id;
        this.subDataList = subDataList;
    }

    public Long getId() { return id; }
    public List<SubData> getSubDataList() { return subDataList; }

    @Override
    public String toString() {
        return "NewResponse{" +
               "id=" + id +
               ", subDataList=" + subDataList +
               '}';
    }
}
登录后复制

2. 实现数据分组与转换逻辑

我们将利用Java Stream API中的Collectors.groupingBy()和Collectors.mapping()这两个强大的收集器来完成数据转换。

步骤一:将原始数据分组到中间Map

首先,将原始的Response对象列表按照id字段进行分组,并将每个组内的Response对象转换为SubData对象列表。

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class DataAggregator {

    public static void main(String[] args) {
        // 模拟原始数据列表
        List<Response> responses = Arrays.asList(
            new ResponseImpl(1L, "UK,FR", "X"),
            new ResponseImpl(2L, "UK,FR", "Y"),
            new ResponseImpl(4L, "EU", "X"),
            new ResponseImpl(4L, "Others", "O")
        );

        // 步骤一:使用groupingBy和mapping进行分组和映射
        Map<Long, List<SubData>> groupedDataMap = responses.stream()
            .collect(Collectors.groupingBy(
                Response::getId, // 分组键:根据Response对象的ID
                Collectors.mapping(
                    r -> new SubData(r.getSData(), r.getSName()), // 下游收集器:将每个Response映射为SubData
                    Collectors.toList() // 将映射后的SubData对象收集成一个列表
                )
            ));

        System.out.println("--- 步骤一:分组后的Map ---");
        groupedDataMap.forEach((id, subDataList) ->
            System.out.println("ID: " + id + ", SubData List: " + subDataList)
        );
        // 预期输出示例:
        // ID: 1, SubData List: [SubData{sData='UK,FR', sName='X'}]
        // ID: 2, SubData List: [SubData{sData='UK,FR', sName='Y'}]
        // ID: 4, SubData List: [SubData{sData='EU', sName='X'}, SubData{sData='Others', sName='O'}]
    }
}
登录后复制
  • Collectors.groupingBy(Response::getId): 这是核心的分组操作,它以Response对象的id作为键来组织数据。
  • Collectors.mapping(r -> new SubData(r.getSData(), r.getSName()), Collectors.toList()): 这是groupingBy的下游收集器。对于每个分组,它会进一步处理该组内的Response对象:首先通过mapping操作将每个Response实例转换为一个SubData实例,然后使用Collectors.toList()将这些SubData实例收集成一个列表。

步骤二:将中间Map转换为最终的NewResponse列表

上一步我们得到了一个Map<Long, List<SubData>>。接下来,我们需要遍历这个Map,将每个键值对(ID和其对应的SubData列表)转换为一个NewResponse对象,并收集成最终的列表。

// ... (接续上面的DataAggregator类)

        // 步骤二
登录后复制

以上就是Java Stream API:高效实现数据分组与嵌套JSON列表转换的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号