如何按值排序Map,值相同时按键排序?我的代码输出不符合预期
按值排序Map,值相同时按键排序的问题
问题场景
我需要实现按值排序Map,当多个条目的值相同时,再按键进行排序,但实际输出与预期不符。
测试代码
Map<PassengerType,Integer> test=new HashMap<>(); test.put(PassengerType.SENIOR_CITIZEN,1); test.put(PassengerType.KID,1); test.put(PassengerType.ADULT,1); List<Map.Entry<PassengerType, Integer>> list = new ArrayList<Map.Entry<PassengerType, Integer>>(test.entrySet()); Collections.sort(list, new ValueThenKeyComparator()); list.stream().forEach(System.out::println);
自定义Comparator代码
public class ValueThenKeyComparator implements Comparator<Map.Entry<PassengerType, Integer>> { public int compare(Map.Entry<PassengerType, Integer> a, Map.Entry<PassengerType, Integer> b) { //System.out.println(a.getValue()+" || "+b.getValue()+" :::"+a.getValue().compareTo(b.getValue())); int valueCompare=a.getValue().compareTo(b.getValue()); if(valueCompare!=0){ return valueCompare; }else{ // System.out.println(a.getKey()+" || "+b.getKey()+" :::"+a.getKey().compareTo(b.getKey())); return a.getKey().compareTo(b.getKey()); } } }
预期输出
ADULT=1 KID=1 SENIOR_CITIZEN=1
实际输出
KID=1 ADULT=1 SENIOR_CITIZEN=1
问题原因及解决方法
问题出在PassengerType枚举的自然排序逻辑上。你的Comparator逻辑本身是正确的——先按值比较,值相同则按键的自然顺序排序,但实际输出不符合预期,说明PassengerType枚举默认的compareTo方法(基于枚举的声明顺序)和你期望的字母顺序不一致。
比如如果你的PassengerType枚举声明顺序是:
public enum PassengerType { KID, ADULT, SENIOR_CITIZEN; }
默认的compareTo会遵循这个声明顺序排序,导致KID排在ADULT前面,和预期的字母顺序不符。
有两种解决方式:
- 调整枚举声明顺序,按照你期望的排序顺序声明:
public enum PassengerType { ADULT, KID, SENIOR_CITIZEN; }
这样默认的compareTo逻辑就会符合预期顺序。
- 修改Comparator的按键比较逻辑,直接按枚举名称的字母顺序比较:
把Comparator中按键比较的代码替换为字符串比较,不受枚举声明顺序影响:
return a.getKey().name().compareTo(b.getKey().name());
这样不管枚举声明顺序如何,都会按照枚举常量的字母顺序排序,确保输出符合预期。
内容的提问来源于stack exchange,提问作者Roshan Saini
相关产品推荐
相关产品推荐

