如何按自定义规则对元素为List<Integer>的ArrayList进行排序?现有Comparator实现无效问题排查
解决List<List>的自定义排序问题
你的排序代码没生效的核心问题是:当两个列表的前缀元素完全相同时,你没有处理它们的长度排序逻辑。比如[1]和[1,1],它们的共同元素完全一致,但你的代码返回了0,排序器会认为这两个列表“相等”,不会调整它们的相对位置,自然达不到你想要的顺序。
正确的排序实现
下面是修正后的Comparator代码,完全符合你期望的排序规则:
Collections.sort(res, new Comparator<List<Integer>>() { public int compare(List<Integer> o, List<Integer> s) { // 先逐个比较两个列表共同长度内的元素 int minLen = Math.min(o.size(), s.size()); for (int i = 0; i < minLen; i++) { int elemCmp = o.get(i).compareTo(s.get(i)); if (elemCmp != 0) { return elemCmp; // 元素不同时,直接返回升序比较结果 } } // 所有共同元素都相同,短列表排在前面 return Integer.compare(o.size(), s.size()); } });
逻辑说明
这个排序逻辑分两步走,完美匹配你的需求:
- 优先比较前缀元素:遍历两个列表中较短的长度,逐个对比对应位置的元素。如果某一位置元素不同,直接返回该元素的升序比较结果(比如
[1,2]和[2],第一个元素1<2,所以[1,2]会排在[2]前面)。 - 前缀相同则按长度排序:如果两个列表的前缀完全一致(比如
[1]和[1,1]、[1,1]和[1,1,2]),此时通过长度比较让短列表排在前面,确保层级递进的顺序。
Java 8+ 简化版
如果你使用的是Java 8或更高版本,可以用Lambda表达式简化代码,逻辑完全一致:
res.sort((list1, list2) -> { int minLen = Math.min(list1.size(), list2.size()); for (int i = 0; i < minLen; i++) { int cmp = list1.get(i).compareTo(list2.get(i)); if (cmp != 0) return cmp; } return Integer.compare(list1.size(), list2.size()); });
测试后,这段代码会将你的原始列表:[1,1,2]、[1,1]、[1,2]、[1]、[2]
排序为你想要的顺序:[1]、[1,1]、[1,1,2]、[1,2]、[2]
内容的提问来源于stack exchange,提问作者Santosh Padavala
相关产品推荐
相关产品推荐

