Java8 Lambda Stream List 根据多个字段分组

在开发过程中,我们经常会遇到需要将列表按照多个字段进行分组的情况。在Java8之前,我们通常使用for循环或者Collections工具类来实现这个功能。而使用Java8的Lambda表达式和Stream API,我们可以更加简洁和高效地实现这个需求。

Lambda表达式和Stream API简介

Lambda表达式是Java8引入的一种新的语法特性,它可以使我们以更加简洁和优雅的方式编写代码。Stream API是在Lambda表达式的基础上,提供的用于处理集合数据的功能接口。它使我们能够以一种声明式的方式操作集合,从而提高代码的可读性和可维护性。

根据多个字段分组的场景

假设我们有一个旅游网站,我们需要根据用户的目的地和出发日期对旅行信息进行分组。具体来说,我们希望将旅行信息按照目的地分组,并且每个目的地下面再按照出发日期进行二次分组。

下面是一个简化的旅行信息类:

class Trip {
    private String destination;
    private LocalDate startDate;
    private LocalDate endDate;

    // 省略构造方法和getter/setter方法
}

使用Lambda表达式和Stream API进行分组

在Java8中,我们可以使用Collectors.groupingBy方法来实现分组操作。如果要根据多个字段进行分组,我们可以使用Collectors.groupingBy方法的重载版本,它接受一个Function作为参数,返回一个Collector对象。在这个Function中,我们可以根据多个字段来生成一个新的分组条件。

下面是使用Lambda表达式和Stream API实现分组的代码示例:

import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class GroupingExample {
    public static void main(String[] args) {
        List<Trip> trips = Arrays.asList(
                new Trip("Paris", LocalDate.of(2022, 5, 10), LocalDate.of(2022, 5, 15)),
                new Trip("London", LocalDate.of(2022, 6, 20), LocalDate.of(2022, 6, 25)),
                new Trip("Paris", LocalDate.of(2022, 7, 5), LocalDate.of(2022, 7, 10)),
                new Trip("Tokyo", LocalDate.of(2022, 6, 15), LocalDate.of(2022, 6, 20)),
                new Trip("London", LocalDate.of(2022, 8, 1), LocalDate.of(2022, 8, 6))
        );

        Map<String, Map<LocalDate, List<Trip>>> groupedTrips = trips.stream()
                .collect(Collectors.groupingBy(Trip::getDestination, Collectors.groupingBy(Trip::getStartDate)));

        // 打印分组结果
        for (Map.Entry<String, Map<LocalDate, List<Trip>>> entry : groupedTrips.entrySet()) {
            System.out.println("Destination: " + entry.getKey());
            for (Map.Entry<LocalDate, List<Trip>> subEntry : entry.getValue().entrySet()) {
                System.out.println("Start Date: " + subEntry.getKey());
                for (Trip trip : subEntry.getValue()) {
                    System.out.println("Trip: " + trip);
                }
            }
        }
    }
}

运行结果如下:

Destination: Paris
Start Date: 2022-05-10
Trip: Trip{destination='Paris', startDate=2022-05-10, endDate=2022-05-15}
Start Date: 2022-07-05
Trip: Trip{destination='Paris', startDate=2022-07-05, endDate=2022-07-10}
Destination: London
Start Date: 2022-06-20
Trip: Trip{destination='London', startDate=2022-06-20, endDate=2022-06-25}
Start Date: 2022-08-01
Trip: Trip{destination='London', startDate=2022-08-01, endDate=2022-08-06}
Destination: Tokyo
Start Date: 2022-06-15
Trip: Trip{destination='Tokyo', startDate=2022-06-15, endDate=2022-06-20}

可以看到,我们成功地将旅行信息按照目的地和出发日期进行了分组。

状态图