Java使用Comparator.thenComparing自定义+自然排序顺序异常问题
问题产生原因
错误核心是List.indexOf()方法的返回值规则:当目标元素不在列表中时,会返回-1。你预定义的definedOrder列表有效索引为0(对应Iii)、1(对应Bbb)、2(对应Aaa),所有不在列表中的secondName(如Ooo、Xxx、Rrr)对应的排序键都是-1。默认升序排序时-1 < 0 < 1 < 2,所以非预定义匹配的记录全部排在了符合预定义顺序的记录前面,和thenComparing的执行顺序无关。
解决方法
自定义排序键生成逻辑,将不在预定义列表的元素的权重设置为大于预定义列表最大索引的值,保证它们排在预定义匹配项的后面。同时建议将预定义顺序转成HashMap,避免每次调用indexOf遍历列表,提升大数据量下的排序性能。
修改后的排序代码如下:
// 预定义顺序转成查找Map,O(1)复杂度获取排序权重 Map<String, Integer> orderMap = IntStream.range(0, definedOrder.size()) .boxed() .collect(Collectors.toMap(definedOrder::get, i -> i)); employees.sort( // 第一层排序:预定义顺序,非匹配项默认权重为列表长度,大于所有有效索引 Comparator.comparing((Employee e) -> orderMap.getOrDefault(e.getSecondName(), definedOrder.size())) // 第二层排序:按name自然顺序排序 .thenComparing(Employee::getName) ); // 输出结果和你预期完全一致 for (Employee em : employees){ System.out.println(em.getSecondName() + " / " + em.getName()); }
运行后输出结果:
Iii / Tom Bbb / Ivy Bbb / Jake Aaa / Ann Aaa / Ivy Aaa / Jake Ooo / Keith Xxx / Neil Rrr / Tom
内容的提问来源于stack exchange,提问作者IgorB
相关产品推荐
相关产品推荐

