You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8如何用Collectors.groupingBy按预定义规则分组生成RentalReport

用Java 8 Collectors.groupingBy按预定义规则分组实现RentalReport生成

当然可以!Java 8的Collectors.groupingBy完全支持按预定义的筛选规则进行分组,能帮你替代逐个过滤集合再创建RentalReport的重复逻辑,让代码更简洁优雅。下面是具体的实现思路和代码示例:

1. 先定义绑定筛选规则的枚举

首先你需要把预定义的到期日分组规则封装到枚举类中,每个枚举值对应一个判断Rental到期状态的规则(用Predicate实现),同时提供一个静态方法来把单个Rental映射到对应的枚举值:

import java.time.LocalDate;
import java.util.Arrays;
import java.util.function.Predicate;

public enum RentalExpirationStatus {
    OVERDUE(rental -> rental.getDueDate().isBefore(LocalDate.now())),
    UPCOMING(rental -> {
        LocalDate now = LocalDate.now();
        return rental.getDueDate().isAfter(now) && rental.getDueDate().isBefore(now.plusDays(3));
    }),
    ON_TIME(rental -> {
        LocalDate now = LocalDate.now();
        return rental.getDueDate().isEqual(now) || rental.getDueDate().isAfter(now.plusDays(3));
    });

    private final Predicate<Rental> filterRule;

    RentalExpirationStatus(Predicate<Rental> filterRule) {
        this.filterRule = filterRule;
    }

    // 静态方法:根据Rental的到期日匹配对应的枚举状态
    public static RentalExpirationStatus getStatusForRental(Rental rental) {
        return Arrays.stream(values())
                .filter(status -> status.filterRule.test(rental))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("无法匹配租赁到期状态: " + rental.getId()));
    }
}

2. 使用groupingBy完成分组并生成RentalReport

接下来就可以通过stream()结合Collectors.groupingBy,用上面的枚举映射方法作为分组依据,一次性完成分组,再把分组结果转换为RentalReport对象:

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 假设你的Rental和RentalReport类定义如下:
// class Rental { private LocalDate dueDate; private String id; /* getter方法 */ }
// class RentalReport { private RentalExpirationStatus status; private List<Rental> rentals; /* 构造方法 */ }

public class RentalService {
    public List<RentalReport> generateRentalReports(List<Rental> allRentals) {
        // 第一步:按预定义的枚举规则分组
        Map<RentalExpirationStatus, List<Rental>> groupedByExpiration = allRentals.stream()
                .collect(Collectors.groupingBy(RentalExpirationStatus::getStatusForRental));

        // 第二步:将分组结果转换为RentalReport集合
        return groupedByExpiration.entrySet().stream()
                .map(entry -> new RentalReport(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }
}

关键说明

  • 核心逻辑是把每个Rental映射到对应的枚举值作为分组键,groupingBy会自动把符合同一枚举规则的Rental归为一组。
  • 如果存在可能匹配不到任何枚举规则的Rental,建议在枚举中添加一个UNKNOWN值作为默认返回,避免抛出异常。
  • 这种写法相比逐个过滤,不仅减少了重复代码,还让分组规则集中在枚举类中,后续修改规则只需要调整枚举即可,维护性更强。

内容的提问来源于stack exchange,提问作者jonesy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:04:20