Java中合并Comparator:按优先级再按价格排序的实现方法
解决Java Comparator合并问题:先按优先级,再按价格排序
嘿,我来帮你搞定这个Comparator合并的问题!首先先指出你代码里的一个小笔误,然后再修正逻辑里的潜在问题,最后给出正确的合并方式。
1. 先修正笔误
你尝试合并时写的COMPARATOR_BY_FARE应该是COMPARATOR_BY_PRICE,这是最直接的拼写错误,先改过来。
2. 你的核心思路是对的,但要注意潜在的NPE问题
你想用thenComparing()串联两个Comparator的思路完全正确,这个方法的作用就是:先执行第一个Comparator的排序逻辑,当两个元素被第一个Comparator判定为相等(返回0)时,再用第二个Comparator继续比较。
不过你的原始Comparator有一个隐藏问题:当MyClass实例不是null但isEmpty()为true时,你返回的key是null,而Comparator.comparing()默认使用的自然排序比较器(比如Integer.compareTo())无法处理null值,会抛出NullPointerException。所以我们需要先修复这个问题,再合并Comparator。
3. 正确的实现方式
方式一:先修复单独的Comparator,再合并
首先修正你的两个基础Comparator,给key的比较加上nullsFirst处理:
// 修复后的优先级Comparator:处理isEmpty()返回null的情况 Comparator<? super MyClass> COMPARATOR_BY_PRIORITY = Comparator.nullsFirst( Comparator.comparing( c -> c.isEmpty() ? null : -c.getPriority(), Comparator.nullsFirst(Comparator.naturalOrder()) ) ); // 修复后的价格Comparator Comparator<? super MyClass> COMPARATOR_BY_PRICE = Comparator.nullsFirst( Comparator.comparing( c -> c.isEmpty() ? null : c.getPrice(), Comparator.nullsFirst(Comparator.naturalOrder()) ) ); // 合并:先按优先级,再按价格 Comparator<? super MyClass> COMBINED_COMPARATOR = COMPARATOR_BY_PRIORITY.thenComparing(COMPARATOR_BY_PRICE);
方式二:直接链式构建合并后的Comparator(更简洁)
如果不需要单独使用那两个基础Comparator,直接链式写出来更紧凑,而且可以优化null处理的次数(外层只需要一次nullsFirst,因为null元素会被直接排在最前面,后面的逻辑不会处理null):
Comparator<? super MyClass> COMBINED_COMPARATOR = Comparator.nullsFirst( Comparator.comparing( (MyClass c) -> c.isEmpty() ? null : -c.getPriority(), Comparator.nullsFirst(Comparator.naturalOrder()) ).thenComparing( c -> c.isEmpty() ? null : c.getPrice(), Comparator.nullsFirst(Comparator.naturalOrder()) ) );
4. 逻辑说明
Comparator.nullsFirst():将null类型的MyClass实例排在所有非null实例的前面。- 内层的
Comparator.nullsFirst(Comparator.naturalOrder()):处理isEmpty()为true的非null实例(此时key为null),将这些实例排在其他非null、非empty的实例前面。 -c.getPriority():实现优先级的降序排序(优先级数值越大,排名越靠前)。thenComparing():确保优先级相同的元素,再按价格的自然顺序(升序)排序。
内容的提问来源于stack exchange,提问作者Gavriel
相关产品推荐
相关产品推荐

