17370845950

Java中如何通过分组收集集合中的数据
使用Stream API的groupingBy可实现集合分组,如按部门分组员工;结合counting统计数量;支持多级分组和自定义条件,如按姓名首字母分组,灵活高效。

在Java中,可以通过 Stream API 结合 Collectors.groupingBy 方法对集合中的数据进行分组收集。这是处理集合分组最常用且简洁的方式。

使用 groupingBy 进行基本分组

假设有一个员工列表,需要按部门对员工进行分组:

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

class Employee {
    private String name;
    private String department;

    public Employee(String name, String department) {
        this.name = name;
        this.department = department;
    }

    // getter 方法
    public String getDepartment() { return department; }
    public String getName() { return name; }
}

public class GroupExample {
    public static void main(String[] args) {
        List employees = Arrays.asList(
            new Employee("Alice", "HR"),
            new Employee("Bob", "IT"),
            new Employee("Charlie", "IT"),
            new Employee("David", "HR")
        );

        Map> grouped = employees.stream()
            .collect(Collectors.groupingBy(Employee::getDepartment));

        grouped.forEach((dept, empList) -> {
            System.out.println(dept + ": " + empList.size() + " 人");
        });
    }
}

按条件分组并统计数量

如果只关心每个组的数量,可以使用 groupingBy 配合 Collectors.counting()

Map countByDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));

// 输出:{HR=2, IT=2}

多级分组(嵌套分组)

可以实现先按一个字段分组,再在子组中按另一个字段分组。例如:先按部门,再按姓名长度分组:

Map>> nestedGroup = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.groupingBy(emp -> emp.getName().length())
    ));

自定义分组条件

分组键不局限于对象属性,也可以是任意表达式。例如:将员工按名字首字母分组:

Map> groupByFirstLetter = employees.stream()
    .collect(Collectors.groupingBy(emp -> emp.getName().charAt(0)));

// 输出如:A=[Alice], B=[Bob], C=[Charlie], D=[David]

基本上就这些。通过 Stream 的 groupingBy,可以灵活实现各种分组需求,代码清晰且易于维护。关键是理解分组器的组合方式,比如配合 counting、mapping、filtering 等下游收集器使用。