如何使用Comparator对TreeMap条件排序:无下划线保插入顺序,有下划线放末尾
解决方案
问题根因
你的原有实现存在两个核心问题:
compare方法中的order变量未做局部声明,大概率是类成员变量,多次比较调用时会互相覆盖值,排序逻辑完全混乱。- TreeMap本身是基于排序规则的有序Map,默认不保留插入顺序,你没有额外维护无下划线key的插入顺序,所以无下划线的key会按字符串自然排序,自然排序下
bbbb小于cccc,就会出现在cccc前面,不符合你的需求。
修改后的实现思路
自定义Comparator内部维护插入序号映射,按以下优先级排序:
- 无下划线的key统一排在有下划线的key前面
- 同属于无下划线的key,按插入顺序升序排列
- 同属于有下划线的key,可按需选择排序规则
完整代码
import java.util.*; class Order implements Comparator<String> { // 存储无下划线key的插入序号 private final Map<String, Integer> insertOrderMap = new HashMap<>(); // 插入序号计数器 private int sequence = 0; @Override public int compare(String o1, String o2) { // 给首次出现的无下划线key分配插入序号 assignSequenceIfNeeded(o1); assignSequenceIfNeeded(o2); boolean o1HasUnderline = o1.contains("_"); boolean o2HasUnderline = o2.contains("_"); // 跨分组比较:无下划线的排前面 if (o1HasUnderline && !o2HasUnderline) { return 1; } if (!o1HasUnderline && o2HasUnderline) { return -1; } // 同无下划线分组:按插入顺序排序 if (!o1HasUnderline) { return insertOrderMap.get(o1) - insertOrderMap.get(o2); } // 同有下划线分组:如需和示例完全一致的顺序,替换为return o2.compareTo(o1)即可 return o1.compareTo(o2); } private void assignSequenceIfNeeded(String key) { if (!key.contains("_") && !insertOrderMap.containsKey(key)) { insertOrderMap.put(key, sequence++); } } } class Test { public static void main(String[] args) { Map<String, String> treeMap= new TreeMap<>(new Order()); treeMap.put("ccc_aaaa", "test"); treeMap.put("aaaa", "test"); treeMap.put("cccc", "test"); treeMap.put("bbbb", "test"); treeMap.put("ccc", "test"); treeMap.put("c_a", "test"); System.out.println(treeMap); } }
可选调整
如果你需要有下划线的key也按插入顺序排列,只需要修改assignSequenceIfNeeded方法的判断逻辑,去掉!key.contains("_")的限制,然后有下划线分组的比较逻辑也改成按插入序号比较即可。
内容的提问来源于stack exchange,提问作者vishnuk
相关产品推荐
相关产品推荐

