Stream 实战:博客列表排序、过滤与分页(AI 辅助学习 Java 8)

前两周学了 Lambda、函数式接口和 Stream 基础。今天在一个完整的博客接口场景中,用 Stream 实现排序、过滤、分页、统计功能。


一、通用分页:排序 + skip + limit

分页是后端最常见的功能。用 Stream 实现只需要三行:

java 复制代码
public List<Blog> getBlogsByPage(int page, int pageSize) {
    return blogs.stream()
            .sorted(Comparator.comparing(Blog::getCreateTime).reversed()) // 最新在前
            .skip((long) (page - 1) * pageSize)   // 跳过前面的数据
            .limit(pageSize)                       // 取一页
            .collect(Collectors.toList());
}

核心公式skip((page - 1) * pageSize)

页码 pageSize skip limit
第1页 10 0 10
第2页 10 10 10
第3页 10 20 10

二、带条件的分页:先过滤再分页

实际场景中,分页往往带有筛选条件:

java 复制代码
// 只看已发布的文章,按阅读量降序分页
public List<Blog> getPublishedByPage(int page, int pageSize) {
    return blogs.stream()
            .filter(Blog::isPublished)
            .sorted(Comparator.comparingInt(Blog::getViews).reversed())
            .skip((long) (page - 1) * pageSize)
            .limit(pageSize)
            .collect(Collectors.toList());
}

三、搜索 + 分页

关键词搜索后分页返回:

java 复制代码
public List<Blog> searchAndPaginate(String keyword, int page, int pageSize) {
    return blogs.stream()
            .filter(b -> b.getTitle().toLowerCase().contains(keyword.toLowerCase())
                    || b.getAuthor().contains(keyword))
            .skip((long) (page - 1) * pageSize)
            .limit(pageSize)
            .collect(Collectors.toList());
}

// 同时获取总数
long total = blogs.stream()
        .filter(b -> b.getTitle().toLowerCase().contains(keyword.toLowerCase()))
        .count();

四、统计面板:分组 + 聚合

按作者统计文章数和总阅读量

java 复制代码
Map<String, AuthorStats> stats = blogs.stream()
        .collect(Collectors.groupingBy(
                Blog::getAuthor,
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> new AuthorStats(
                                list.size(),
                                list.stream().mapToInt(Blog::getViews).sum()
                        )
                )
        ));

输出:

makefile 复制代码
张三: 3 篇, 总阅读 530
李四: 2 篇, 总阅读 750
王五: 2 篇, 总阅读 750

按标签统计文章数

java 复制代码
blogs.stream()
        .flatMap(b -> b.getTags().stream())  // 展平所有标签
        .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()))
        .entrySet().stream()
        .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
        .forEach(entry -> System.out.println("  " + entry.getKey() + ": " + entry.getValue() + " 篇"));

输出:

makefile 复制代码
Java: 4 篇
前端: 2 篇
Optional: 1 篇
Docker: 1 篇
...

五、数据校验:allMatch / anyMatch

用 Stream 做数据校验也很方便:

java 复制代码
// 所有文章都有标题吗?
boolean allHaveTitle = blogs.stream()
        .allMatch(b -> b.getTitle() != null && !b.getTitle().isEmpty());

// 有没有作者名为空的?
boolean hasEmptyAuthor = blogs.stream()
        .anyMatch(b -> b.getAuthor() == null || b.getAuthor().isEmpty());

六、运行结果

本项目 StreamPaginationDemo.java 完整运行结果:

csharp 复制代码
=== 1. 分页查询 ===
  第 1 页 (每页3条):
    [2026-06-12T12:00] Java 8 Optional 最佳实践
    [2026-06-11T08:00] Docker 入门指南
    [2026-06-09T11:00] React Hooks 教程
  第 2 页:
    [2026-06-07T16:00] Java Stream API 详解
    [2026-06-05T09:00] Vue3 组合式 API
    [2026-06-03T14:00] Spring Boot 实战

=== 2. 带条件分页 ===
  已发布-第1页-按阅读量降序:
    [500阅读] Vue3 组合式 API
    [400阅读] React Hooks 教程

=== 3. 搜索 + 分页 ===
  搜索 'Java' 第1页:
    Java 8 Lambda 入门 (张三)
    Java Stream API 详解 (张三)
    Java 8 Optional 最佳实践 (张三)
  共 3 条结果

=== 4. 统计面板 ===
  张三: 3 篇, 总阅读 530
  李四: 2 篇, 总阅读 750
  王五: 2 篇, 总阅读 750
  各标签文章数:
    Java: 4 篇
    前端: 2 篇

=== 5. 数据校验 ===
  所有文章都有标题: true
  有空作者名: false

七、本周学习总结

第三周我们学习了 Stream API,完整路线:

python 复制代码
周二:Stream API 入门------创建、中间操作、终端操作
周四:filter/map/sorted------三个最常用的操作
周六:分页+搜索+统计------博客接口实战(本篇)

核心收获

知识点 关键方法 一句话
创建 Stream stream() / of() / generate() 数据源 → 流
过滤 filter(Predicate) 只要匹配的
转换 map(Function) 一对一转换
扁平化 flatMap 一对多再展平
排序 sorted(Comparator) 按规则排序
分页 skip(n) + limit(n) 跳过 + 取
统计 count() / sum() / average() 聚合计算
匹配 anyMatch / allMatch / noneMatch 是否有匹配

八、下周预告

第四周进入 Stream 进阶:Collectors 全家桶(toList/joining/groupingBy/partitioningBy)、flatMap 深入、以及数据统计的完整实战。


系列文章导航

更多请关注我的微信公众号,感谢!

相关推荐
长谷深风1115 分钟前
AI Tool 设计:粒度、参数与错误恢复怎么做
java·大数据·人工智能·ai agent·agent工作流·智能体设计·ai产品设计
__zRainy__10 分钟前
Node系列 · 数据库:单表查询
数据库·后端·mysql·node.js
雪芽蓝域zzs10 分钟前
Element‑Plus icon 图标名称查询 & 和菜单 meta.icon 字段映射
前端
诺伦16 分钟前
Rust 错误处理实战:从 unwrap 到优雅 Result 的进阶之路
开发语言·后端·rust
01_ice1 小时前
前端学习css
前端·css·学习
不能放弃治疗1 小时前
上下文压缩机制
后端
QQ_21696290961 小时前
【项目编号:project95315】SpringBoot公共自习室管理系统:座位预约、房间管理、签到核销、公告规则完整实战
java·spring boot·后端
愚公搬代码1 小时前
【愚公系列】《Web应用安全》010-Repeater模块的使用
前端·安全
凤山老林1 小时前
高可用服务容错架构:Spring Boot 集成 Resilience4j 实战指南
spring boot·后端·架构·resilience4j
手握风云-2 小时前
Spring Cloud:分布式系统的“粘合剂”(五)
后端·spring·spring cloud