使用 Java Stream 合并 List 中的重复数据

在日常的 Java 开发中,我们经常会遇到需要处理集合数据的情况,包括合并 List 中的重复元素。在 Java 8 引入 Stream API 后,处理集合变得更加方便和直观。本文将通过实例详细介绍如何使用 Java Stream 来合并 List 中的重复数据,并在文中使用关系图和序列图辅助说明。

1. 背景简介

在许多应用场景中,集合中可能会存在重复的数据,而我们希望能够在处理时合并这些重复数据,以便后续处理更加高效。比如在用户数据中,可能会存在多个用户记录相同的电子邮件地址,我们需要将其合并为一条记录。

示例需求

假设我们有一个用户数据列表,结构如下:

  • id: 用户ID
  • email: 用户电子邮件
  • name: 用户姓名

目标是根据邮箱(email)去重,合并重复的用户记录。

2. 示例数据

首先,我们来定义一个用户类 (User),并创建一个包含重复用户的列表。

public class User {
    private int id;
    private String email;
    private String name;

    // 构造函数
    public User(int id, String email, String name) {
        this.id = id;
        this.email = email;
        this.name = name;
    }

    // Getter 和 Setter 省略
}

接着,创建一个包含重复用户的 List:

List<User> users = Arrays.asList(
    new User(1, "john@example.com", "John Doe"),
    new User(2, "jane@example.com", "Jane Doe"),
    new User(3, "john@example.com", "Johnathan Doe"),
    new User(4, "jane@example.com", "Janet Doe")
);

3. 使用 Java Stream 进行合并

下面演示如何使用 Java Stream API 合并这些重复的用户记录。

import java.util.*;
import java.util.stream.Collectors;

List<User> mergedUsers = users.stream()
    .collect(Collectors.toMap(
        User::getEmail, // 使用 email 作为 key
        user -> user,   // value 是用户对象
        (existing, newUser) -> new User(existing.getId(), existing.getEmail(), existing.getName() + ", " + newUser.getName()) // 合并姓名
    ))
    .values()
    .stream()
    .collect(Collectors.toList());

解释

  1. Collectors.toMap: 将 Stream 中的元素收集至一个 Map,key 为用户的 email,value 为用户对象。
  2. 合并策略: 当遇到重复的 email 时,使用 lambda 表达式定义如何合并。这里我们选择保留第一个 user's ID 和 email,而将姓名进行合并。
  3. 获取结果: 通过 values() 方法提取所有用户,最终转换为 List。

4. 结果

执行上述代码后,mergedUsers 将只包含:

  • John Doe: john@example.com (合并为 "John Doe, Johnathan Doe")
  • Jane Doe: jane@example.com (合并为 "Jane Doe, Janet Doe")

5. 可视化关系图

为了帮助理解数据之间的关系,我们使用 mermaid 语法展示数据模型。

erDiagram
    USER {
        int id PK "用户ID"
        string email "用户电子邮件"
        string name "用户姓名"
    }

6. 流程序列图

为了说明执行合并操作的流程,以下是相关的序列图:

sequenceDiagram
    participant U as User List
    participant S as Stream API
    participant C as Collector
    
    U->>S: 创建 Stream
    S->>C: 收集到 Map
    C-->>S: 返回 Map
    S->>U: 提取 merged Users

7. 总结

在这篇文章中,我们介绍了如何使用 Java Stream API 并结合 Collector 来合并 List 中的重复数据。通过合并相同邮箱的用户记录,我们可以更好地管理用户信息,提高数据处理的效率。这种方法不仅适用于用户数据的合并,也可以扩展到其他场景中,如订单记录、产品信息等。

随着对 Java Stream 越来越深入的理解,开发者可以通过更巧妙的方式来处理复杂的数据处理需求,提升代码的可读性和简洁性。希望本文能帮助开发者更好地运用 Java Stream 进行数据处理。如果你在实际开发中遇到相似的问题,不妨尝试这个方法。