如何按List B的元素顺序高效排序List A?
高效实现列表按另一个列表顺序排序的方案
问题分析
你需要将列表A[1,2,4,5,6,7,8,9]按照列表B[6,3,8,2]的元素顺序排序,最终得到[6,8,2,1,4,5,7,9]——核心需求是:A中存在于B的元素按B的顺序排在前面,A中剩余元素保持原顺序排在后面。
你之前的代码存在三个问题:
- 逻辑方向错误:你对
listB进行排序,但实际需要排序的是listA; - 列表不可修改问题:如果
listB是通过Arrays.asList()创建的,调用sort()会抛出UnsupportedOperationException,因为该方法返回的是固定大小的不可修改列表; - 效率低下:使用
listA.indexOf(element)每次都会遍历listA,时间复杂度为O(n*m),列表较大时性能很差。
高效实现方案
通过构建两个HashMap将查找操作降到O(1),整体排序时间复杂度为O(n log n),具体实现如下:
完整代码
import java.util.*; import java.util.stream.Collectors; public class SortByReferenceList { public static void main(String[] args) { List<Integer> listA = new ArrayList<>(Arrays.asList(1, 2, 4, 5, 6, 7, 8, 9)); List<Integer> listB = Arrays.asList(6, 3, 8, 2); // 1. 构建优先级映射:记录B中存在于A的元素及其在B中的索引 Map<Integer, Integer> priorityMap = new HashMap<>(); for (int i = 0; i < listB.size(); i++) { Integer elem = listB.get(i); if (listA.contains(elem)) { priorityMap.put(elem, i); } } // 2. 构建原索引映射:记录A中元素的原始位置,用于保持剩余元素的原顺序 Map<Integer, Integer> originalIndexMap = new HashMap<>(); for (int i = 0; i < listA.size(); i++) { originalIndexMap.put(listA.get(i), i); } // 3. 对A进行排序 List<Integer> sortedA = listA.stream() .sorted((a, b) -> { int prioA = priorityMap.getOrDefault(a, Integer.MAX_VALUE); int prioB = priorityMap.getOrDefault(b, Integer.MAX_VALUE); // 优先按B中的顺序排序 if (prioA != prioB) { return Integer.compare(prioA, prioB); } // 不在B中的元素保持原列表的相对顺序 return Integer.compare(originalIndexMap.get(a), originalIndexMap.get(b)); }) .collect(Collectors.toList()); System.out.println(sortedA); // 输出: [6, 8, 2, 1, 4, 5, 7, 9] } }
关键细节说明
- 优先级映射:把B中存在于A的元素映射到它们在B中的索引,排序时直接通过索引值确定顺序,避免重复遍历A;
- 原索引映射:确保A中不在B里的元素保持原来的相对顺序,完全匹配你给出的目标结果;
- 灵活调整:如果不需要保持剩余元素的原顺序,而是要按自然升序排列,可将排序逻辑的else分支改为
return Integer.compare(a, b); - 避免不可修改列表问题:如果需要对B进行操作,记得将其转换为可修改列表(比如
new ArrayList<>(Arrays.asList(...)))。
内容的提问来源于stack exchange,提问作者sreenu yalam
相关产品推荐
相关产品推荐

