Java8中List按多个字段分组和映射

在Java编程中,我们经常需要对列表进行分组和映射操作。而在Java 8中,引入了lambda表达式和Stream API,使得这些操作更加简洁和高效。本文将介绍如何使用Java 8对List按多个字段进行分组和映射的方法,并提供相应的代码示例。

为什么需要按多个字段分组和映射

在数据处理中,有时候我们需要根据多个字段来对数据进行分类和聚合,这样可以更精准地对数据进行分析和处理。比如,我们有一个包含员工信息的列表,我们希望按照部门和性别对员工进行分组,并统计每个部门每种性别的人数。这时候就需要按照多个字段进行分组和映射操作。

使用Java 8对List进行多字段分组

在Java 8中,我们可以使用Stream API中的Collectors.groupingBy方法来对List进行分组操作。对于多字段分组,我们可以使用Collectors.groupingBy方法的重载版本,传入多个分类器即可实现按多个字段分组的功能。

下面是一个示例代码,演示了如何对员工列表按照部门和性别进行分组:

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

class Employee {
    private String department;
    private String gender;

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

    public String getDepartment() {
        return department;
    }

    public String getGender() {
        return gender;
    }
}

public class GroupingByMultipleFields {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                new Employee("HR", "Male"),
                new Employee("HR", "Female"),
                new Employee("IT", "Male"),
                new Employee("IT", "Female")
        );

        Map<String, Map<String, List<Employee>>> groupedByDepartmentAndGender = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                        Collectors.groupingBy(Employee::getGender)));

        groupedByDepartmentAndGender.forEach((department, genderMap) -> {
            System.out.println(department + ": ");
            genderMap.forEach((gender, employeeList) -> {
                System.out.println("  " + gender + ": " + employeeList.size());
            });
        });
    }
}

在上面的代码中,我们首先创建了一个Employee类来表示员工信息,包含部门和性别两个字段。然后创建了一个包含员工信息的列表,并使用Collectors.groupingBy方法按照部门和性别进行分组,最后输出每个部门每种性别的员工人数。

使用Java 8对List进行多字段映射

除了分组操作,有时候我们还需要对分组后的数据进行映射处理,比如统计每个部门每种性别的平均工资。在Java 8中,我们可以使用Collectors.collectingAndThen方法来对分组后的数据进行进一步处理。

下面是一个示例代码,演示了如何对员工列表按照部门和性别进行分组,并计算每个部门每种性别的平均工资:

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

class Employee {
    private String department;
    private String gender;
    private double salary;

    public Employee(String department, String gender, double salary) {
        this.department = department;
        this.gender = gender;
        this.salary = salary;
    }

    public String getDepartment() {
        return department;
    }

    public String getGender() {
        return gender;
    }

    public double getSalary() {
        return salary;
    }
}

public class MappingByMultipleFields {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                new Employee("HR", "Male", 5000),
                new Employee("HR", "Female", 6000),
                new Employee("IT", "Male", 7000),
                new Employee("IT", "Female", 8000)
        );

        Map<String, Map<String, Double>> averageSalaryByDepartmentAndGender = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                        Collectors.groupingBy(Employee::getGender,
                                Collectors.collectingAndThen(
                                        Collectors.averagingDouble(Employee::getSalary),
                                        avg -> Math.round(avg * 100.0) / 100.0))));

        averageSalaryByDepartmentAndGender.forEach((department, gender