Java中基于可变排序规则列表实现对象排序并避免switch语句的方案
优化方案
核心思路是将排序字段和对应的属性提取逻辑绑定到已有的MunroSortingFields枚举中,直接通过枚举实例获取比较器生成所需的提取函数,完全消除switch分支。
第一步:改造枚举类,维护字段与提取函数的映射
在MunroSortingFields枚举中新增属性提取器字段,每个枚举值对应Munro对应属性的getter引用:
public enum MunroSortingFields { NAME("name", Munro::getName), HEIGHT("height", Munro::getHeight), CATEGORY("category", Munro::getCategory), GRID_REFERENCE("gridReference", Munro::getGridReference); // 原有的参数字段 public final String param; // 新增:属性提取函数,用于生成比较器 public final Function<Munro, Comparable> valueExtractor; MunroSortingFields(String param, Function<Munro, Comparable> valueExtractor) { this.param = param; this.valueExtractor = valueExtractor; } // 可选新增:根据请求参数字符串匹配枚举实例,用于参数转换阶段校验 public static MunroSortingFields of(String param) { return Arrays.stream(values()) .filter(field -> field.param.equals(param)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("非法排序字段: " + param)); } }
第二步:重写sort方法,消除switch分支
直接从排序字段对应的枚举实例中拿提取函数生成比较器即可:
private Stream<Munro> sort(MunroRequest munroRequest, Stream<Munro> munroStream) { // 保留原有的默认排序规则 Comparator<Munro> munroComparator = Comparator.comparing(Munro::getGridReference); for (MunroSort sortItem : munroRequest.getMunroSorts()) { // 直接通过枚举的提取函数生成本次排序的比较器 Comparator<Munro> itemComparator = Comparator.comparing(sortItem.getFieldToSort().valueExtractor); // 处理降序逻辑 if (!sortItem.isAscending()) { itemComparator = itemComparator.reversed(); } // 拼接进总比较器 munroComparator = munroComparator.thenComparing(itemComparator); } return munroStream.sorted(munroComparator); }
方案优势
- 完全消除switch冗余分支,后续新增排序字段仅需在
MunroSortingFields中新增一行枚举定义即可,无需修改排序逻辑,符合开闭原则 - 无反射调用,类型安全,性能和原有switch实现一致
- 所有排序字段相关的映射逻辑集中在枚举类中维护,不会散落在业务代码里,便于统一管理
如果需要避免自动装箱带来的微小性能损耗,也可以针对不同属性类型拆分提取器接口,比如对height字段用ToDoubleFunction<Munro>,大部分场景下上述实现已经足够满足需求。
内容的提问来源于stack exchange,提问作者Sam Spain
相关产品推荐
相关产品推荐

