Java Stream 根据一个字段去重

在Java 8发布后,Stream API成为了处理集合数据的一种强大工具。通过Stream API,我们可以轻松实现过滤、映射和减少等操作。而在许多实际应用中,我们常常需要根据某个字段对数据进行去重。本文将详细说明如何使用Java Stream以及相关实例来实现根据字段去重的功能。

什么是Java Stream?

Java Stream是一个处理数据流的接口,允许数组、集合等数据结构以声明性方式进行操作。使用Stream,我们可以更简洁地进行数据处理,例如过滤(filter)、映射(map)、聚合(reduce)等操作。

示例场景

假设我们有一个Person类,包含nameage两个字段。现在我们有一个List<Person>,我们需要根据name字段去重,最终得到一个只包含唯一名字的人员列表。

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

class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 20),
            new Person("Alice", 25),
            new Person("Charlie", 35)
        );

        // 根据name字段去重
        List<Person> distinctPeople = people.stream()
            .filter(distinctByKey(Person::getName))
            .collect(Collectors.toList());

        distinctPeople.forEach(person -> 
            System.out.println("Name: " + person.getName() + ", Age: " + person.age)
        );
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}

代码解析

  1. 创建Person:该类包含nameage两个属性,构造函数和一个用来获取姓名的getter方法。
  2. 创建人员列表:使用Arrays.asList方法初始化一个人员列表,包含同名但不同年龄的人员。
  3. 去重操作
    • 使用stream()方法将人员列表转化为流。
    • filter方法结合自定义的distinctByKey方法来根据name字段去重。
    • 使用collect(Collectors.toList())将结果收集到新的列表中。
  4. 打输出结果:遍历去重后的列表并打印每个人员的姓名和年龄。

关系图

以下是通过Mermaid语法绘制的Person类的ER图:

erDiagram
    PERSON {
        String name
        Integer age
    }

序列图

以下是一个描述人员去重过程的序列图,展示了各个过程如何相互作用:

sequenceDiagram
    participant User
    participant List
    participant Stream
    participant Collector

    User->>List: Creates a list of Person
    User->>Stream: Calls stream() on List
    Stream->>Filter: Filters duplicates
    Filter->>Collector: Collects unique items
    Collector-->>User: Returns distinct Person list

结尾

通过本文的介绍,我们了解了如何利用Java Stream API根据特定字段进行数据去重的操作。通过自定义的 distinctByKey 方法,可以灵活实现根据任意字段去重,极大地简化了代码的复杂性。Stream API为Java开发者提供了一种更易读、优雅的方式处理集合数据。希望本文能为你在Java开发中带来帮助,让你的数据处理变得更高效。