Java 8基于分层优先级实现流过滤 命中即停返回匹配学生对象
优化思路
原实现的核心冗余点:
- 每新增一个优先级专业,就要复制一遍stream过滤的代码块,重复代码占比超过80%
- 优先级顺序写死在代码执行流里,调整顺序需要改动核心执行逻辑
- 后续新增筛选规则时,代码体量会和规则数量线性增长,维护成本高
优化核心是把优先级规则本身抽象成有序的数据结构,和执行逻辑解耦——规则的顺序、判断条件全部存在数据结构里,执行逻辑只需要按顺序遍历规则、命中即返回即可,后续调整规则完全不需要改动核心执行代码。
具体实现
1. 基础简化版(适配当前仅按专业优先级筛选的场景)
直接用有序列表维护专业枚举的优先级顺序,执行逻辑统一遍历优先级列表做匹配,完全消除重复代码:
import java.util.List; import java.util.Optional; public class Question { // 按优先级从高到低排列的专业枚举,新增/调整规则只需要修改这个列表即可 private static final List<Module> PRIORITY_MODULES = List.of( Module.COMP, Module.ECON, Module.AGRI // 后续要新增优先级规则,直接在这里加即可,比如Module.PHYS ); public static Student filterStudent(List<Student> studentList) throws Exception { // 按优先级顺序逐个匹配,命中即返回 for (Module module : PRIORITY_MODULES) { String targetModuleName = module.getModuleName(); Optional<Student> matchedStudent = studentList.stream() .filter(student -> student.getStModule().equalsIgnoreCase(targetModuleName)) .findFirst(); if (matchedStudent.isPresent()) { return matchedStudent.get(); } } throw new Exception("No student found matching criteria"); } // 其余main方法、Student类、Module枚举的定义和原代码保持一致 }
这个版本的优势:
- 调整优先级顺序只需要修改
PRIORITY_MODULES列表的元素顺序,完全不用动过滤执行代码 - 新增筛选规则只需要往列表里加对应枚举值,没有冗余的重复代码
- 命中第一个匹配的结果就立刻返回,执行逻辑和原代码完全等价
2. 灵活扩展版(支持自定义非专业类的优先级规则)
如果后续优先级规则不只是匹配专业,还有比如匹配学号范围、特殊身份标记等非固定字段的规则,可以把规则抽象成函数式的判断条件,配合链式调用风格的通用匹配器实现全场景适配:
首先封装一次通用的优先级匹配器(后续所有类似的优先级筛选场景都可以复用):
import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.Predicate; // 通用优先级匹配器:按规则添加的先后顺序作为优先级从高到低,命中即返回 class PriorityMatcher<T> { private final List<Predicate<T>> ruleList = new ArrayList<>(); public static <T> PriorityMatcher<T> builder() { return new PriorityMatcher<>(); } // 链式添加筛选规则,先添加的规则优先级更高 public PriorityMatcher<T> addRule(Predicate<T> rule) { this.ruleList.add(rule); return this; } // 对目标列表执行匹配,返回第一个命中最高优先级规则的结果 public Optional<T> match(List<T> targetList) { for (Predicate<T> rule : ruleList) { Optional<T> matched = targetList.stream() .filter(rule) .findFirst(); if (matched.isPresent()) { return matched; } } return Optional.empty(); } }
之后filterStudent方法就可以写成链式调用的简洁风格:
public static Student filterStudent(List<Student> studentList) throws Exception { return PriorityMatcher.<Student>builder() // 最高优先级:匹配COMP专业学生 .addRule(s -> s.getStModule().equalsIgnoreCase(Module.COMP.getModuleName())) // 次优先级:匹配ECON专业学生 .addRule(s -> s.getStModule().equalsIgnoreCase(Module.ECON.getModuleName())) // 第三优先级:匹配AGRI专业学生 .addRule(s -> s.getStModule().equalsIgnoreCase(Module.AGRI.getModuleName())) // 后续新增自定义规则直接链式追加即可,比如:匹配学号大于40的学生 // .addRule(s -> s.getStNumber() > 40) .match(studentList) .orElseThrow(() -> new Exception("No student found matching criteria")); }
验证说明:优化后的代码运行输出和原代码完全一致,不会改变原有筛选规则的匹配结果,同时支持无侵入扩展新的优先级规则。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

