331. Java Stream API - Java Stream 实战案例:找出合作最多的作者对

331. Java Stream API - Java Stream 实战案例:找出合作最多的作者对

🎯 目标

在一堆文章(Article)中,找出一起合作写文章次数最多的两个作者(Author)


🧩 数据模型设计

我们有三个核心模型:

java 复制代码
// 作者,支持按名字排序
record Author(String name) implements Comparable<Author> {
    public int compareTo(Author other) {
        return this.name.compareTo(other.name);
    }
}

// 文章
record Article(String title, int inceptionYear, List<Author> authors) {}

// 作者对(避免重复,如 A-B 和 B-A 视为同一对)
record PairOfAuthors(Author first, Author second) {
    public static Optional<PairOfAuthors> of(Author first, Author second) {
        // 确保作者对排序一致(避免 A-B 和 B-A)
        if (first.compareTo(second) > 0) {
            return Optional.of(new PairOfAuthors(first, second));
        } else {
            return Optional.empty();
        }
    }
}

📌 PairOfAuthors.of()Optional 表示"是否是有效的作者对",这样可以方便后续的流式处理。


🏗️ 构建作者对流

第一步是:从每篇文章中提取所有合法的作者对。

java 复制代码
BiFunction<Article, Author, Stream<PairOfAuthors>> buildPairOfAuthors =
    (article, firstAuthor) ->
        article.authors().stream()
               .flatMap(secondAuthor ->
                   PairOfAuthors.of(firstAuthor, secondAuthor).stream());

🔍 如果 PairOfAuthors.of() 返回 Optional.empty(),那么 stream() 就是空流,否则是单元素流。这样可以优雅地处理无效对。


🔁 展平所有文章的作者对

java 复制代码
Function<Article, Stream<PairOfAuthors>> toPairOfAuthors =
    article -> article.authors().stream()
                      .flatMap(firstAuthor -> buildPairOfAuthors.apply(article, firstAuthor));

💡 我们对每篇文章的作者使用 flatMap(),构建所有可能的作者对(去除无效)。


📊 构建作者对出现频次的直方图

java 复制代码
Map<PairOfAuthors, Long> numberOfAuthorsTogether =
    articles.stream()
            .flatMap(toPairOfAuthors)
            .collect(Collectors.groupingBy(
                Function.identity(),
                Collectors.counting()));

📦 用 groupingBy + counting() 聚合每对作者出现的次数。


🥇 找出合作最多的一对作者

java 复制代码
Function<Map<PairOfAuthors, Long>, Map.Entry<PairOfAuthors, Long>> maxExtractor =
    map -> map.entrySet().stream()
              .max(Map.Entry.comparingByValue())
              .orElseThrow();

☂️ orElseThrow() 会在没有任何作者对时抛异常,所以要确保至少有一篇文章包含两个作者。


🧪 示例数据和完整运行逻辑

java 复制代码
var maria = new Author("Maria");
var james = new Author("James");
var patricia = new Author("Patricia");
var michael = new Author("Michael");

var articles = List.of(
    new Article("About As You Like It", 2015, List.of(maria)),
    new Article("About King John", 2015, List.of(james)),
    new Article("About The Winter's Tale", 2016, List.of(patricia)),
    new Article("About Richard II", 2017, List.of(michael)),
    new Article("About Richard III", 2019, List.of(maria, patricia)),
    new Article("About Henry VIII", 20219, List.of(patricia, michael)),
    new Article("About Romeo and Juliet", 2020, List.of(maria, patricia, james)),
    new Article("About Macbeth", 2021, List.of(maria, james, michael)),
    new Article("About Hamlet", 2021, List.of(patricia, james, michael)),
    new Article("About King Lear", 2022, List.of(maria, james, patricia, michael))
);

Map.Entry<PairOfAuthors, Long> pair = maxExtractor.apply(numberOfAuthorsTogether);

System.out.println("The authors that published the most together are " +
    pair.getKey().first().name() + " and " + pair.getKey().second().name() +
    ", they wrote " + pair.getValue() + " articles together.");

🧾 输出结果:

java 复制代码
The authors that published the most together are Patricia and Michael, they wrote 3 articles together.

💡 小结与思考

✅ 使用 Optional.stream() 可以优雅处理"可能不存在"的值 ✅ 用 flatMap() 组合嵌套结构(多个 List 变为流) ✅ groupingBy + counting 构建频次统计 ✅ max() + orElseThrow() 获取最大值时要注意异常安全性

相关推荐
郭老二3 小时前
【前端】vue3:编译步骤
前端
不在逃避q3 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
mldong3 小时前
从 mldong 到 jeeflow:一个工作流引擎的独立进化
后端
夏殇之殁4 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9854 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易4 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
Aaron - Wistron4 小时前
Web API C# (Furion版)带 单元测试
开发语言·后端·c#
卷无止境5 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境5 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
新中地GIS开发老师5 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发