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
相关产品推荐
相关产品推荐

