Stream 数据统计实战:求和、平均值、分组汇总(AI 辅助学习 Java 8)

前三篇学了 Collectors、flatMap。今天在一个完整的博客数据场景中,综合运用 Stream + Collectors 实现数据统计、分组汇总、标签云、趋势分析。


一、整体概览:一键获取所有统计信息

java 复制代码
IntSummaryStatistics stats = blogs.stream()
        .collect(Collectors.summarizingInt(BlogData::getViews));

stats.getCount();    // 7 篇文章
stats.getSum();      // 2180 总阅读
stats.getAverage();  // 311 平均阅读
stats.getMax();      // 500 最高阅读
stats.getMin();      // 180 最低阅读

一次遍历获取所有统计信息,比分别调用五次高效。

二、按作者分组汇总

java 复制代码
Map<String, AuthorSummary> summaries = blogs.stream()
        .collect(Collectors.groupingBy(
                BlogData::getAuthor,
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> new AuthorSummary(
                                list.size(),                                          // 文章数
                                list.stream().mapToInt(BlogData::getViews).sum(),     // 总阅读
                                list.stream().mapToInt(BlogData::getViews).average().orElse(0), // 平均阅读
                                list.stream().mapToInt(BlogData::getViews).max().orElse(0),     // 最高阅读
                                list.stream().filter(BlogData::isPublished).count()   // 已发布数
                        )
                )
        ));

输出:

makefile 复制代码
张三: 文章 3 篇 (已发布: 2), 总阅读: 730, 平均: 243, 最高: 350
李四: 文章 2 篇 (已发布: 2), 总阅读: 900, 平均: 450, 最高: 500
王五: 文章 2 篇 (已发布: 1), 总阅读: 550, 平均: 275, 最高: 300

三、标签云:flatMap + groupingBy + 排序

java 复制代码
// 统计标签频率
Map<String, Long> tagFrequency = blogs.stream()
        .flatMap(b -> b.getTags().stream())
        .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

// 按频率降序展示
tagFrequency.entrySet().stream()
        .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
        .forEach(e -> System.out.println("  " + e.getKey() + " (" + e.getValue() + ")"));

输出:

scss 复制代码
Java (4)
前端 (2)
Optional (1)
Docker (1)
Vue (1)
...

四、趋势分析:排序 + Top N

阅读量 Top 3

java 复制代码
blogs.stream()
        .sorted(Comparator.comparingInt(BlogData::getViews).reversed())
        .limit(3)
        .forEach(b -> System.out.println("  " + b.getTitle() + " (" + b.getViews() + ")"));

最低阅读量的已发布文章

java 复制代码
blogs.stream()
        .filter(BlogData::isPublished)
        .min(Comparator.comparingInt(BlogData::getViews))
        .ifPresent(b -> System.out.println("  " + b.getTitle() + " (" + b.getViews() + ")"));

五、运行结果

ini 复制代码
=== 整体概览 ===
  文章总数: 7
  总阅读量: 2180
  平均阅读: 311
  最高: 500 / 最低: 180

=== 按作者汇总 ===
  张三: 3 篇, 总阅读 730, 平均 243, 最高 350
  李四: 2 篇, 总阅读 900, 平均 450, 最高 500
  王五: 2 篇, 总阅读 550, 平均 275, 最高 300

=== 按分类统计 ===
  Java: 4 篇
  前端: 2 篇
  运维: 1 篇
  各分类平均阅读: {Java=257.5, 运维=250.0, 前端=450.0}

=== 标签云 ===
  Java #### (4)
  前端 ## (2)
  Stream # (1)
  ...

=== 趋势分析 ===
  阅读量 Top 3:
    Vue3 API (500 阅读)
    React Hooks (400 阅读)
    Stream 详解 (350 阅读)

六、本周学习总结

第四周我们学习了 Collectors 进阶,完整路线:

bash 复制代码
周二:Collectors 全家桶------toList/joining/groupingBy/partitioningBy/summarizing
周四:flatMap 深入------一对多场景、标签提取、反向索引
周六:数据统计实战------求和、平均值、分组汇总、标签云(本篇)

核心收获:

知识点 关键方法 一句话
toList/toSet/toMap 转集合 收集为数据结构
joining 拼接字符串 带分隔符、前后缀
groupingBy 分组 按条件分组 + 下游收集器
partitioningBy 分区 按 true/false 分两组
summarizing 汇总统计 一次获取 count/sum/avg/max/min
flatMap 扁平化 一对多场景的利器
collectingAndThen 后处理 分组后自定义转换

七、下周预告

第五周进入 Optional,学习如何优雅地处理空值,告别 NullPointerException。


系列文章导航:

相关推荐
WeiXin_DZbishe10 分钟前
基于Springboot+AI的kuall音乐广场的设计与实现-计算机毕设 附源码【课程设计】12715
vue.js·人工智能·spring boot·后端·python·php·课程设计
wewowilling16 分钟前
认识微服务
java·运维·微服务·springcloud
A接拉起00727 分钟前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户114818678948432 分钟前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界35 分钟前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
代码什么用36 分钟前
Java Web 7-10
java·servlet
Bazingga40 分钟前
RAG评测体系保姆级教程:生产级实践指南
后端
葡萄城技术团队42 分钟前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一1 小时前
优化修整算法
前端·javascript·算法
tachibana22 小时前
使用for range 的时候,它的地址会发生变化吗?
开发语言·后端·golang·go·语法