如何按已排序ArrayList的顺序对Object数组进行排序?
按参考列表顺序排序Object数组的解决方案
我明白你要做的事:不是用数组去排列表,而是反过来,让你的hits[]数组的元素顺序完全匹配另一个已排好的ArrayList的顺序——本质是把参考列表的顺序当成一个"排序规则"来套用在Object数组上。
你之前的代码报错是因为泛型类型不匹配:你给Comparator指定了ArrayList<Double>作为泛型,但你的hits[]里的元素显然不是ArrayList<Double>类型,所以编译器会报"not applicable"错误。下面是符合你需求的可行实现,思路是先把参考列表的元素和索引做映射,再通过比较元素在参考列表中的位置来排序:
步骤1:先构建参考列表的索引映射
为了避免每次排序比较时都去遍历参考列表找索引(效率很低),我们先把参考列表的元素和它的索引位置存到一个Map里:
// 假设你的已排序参考列表是这个(比如是Double类型,可根据实际调整) List<Double> sortedReferenceList = ...; // 你的已排序列表 // 构建值到索引的映射,快速查找元素在参考列表中的位置 Map<Double, Integer> valueToIndexMap = new HashMap<>(); for (int i = 0; i < sortedReferenceList.size(); i++) { valueToIndexMap.put(sortedReferenceList.get(i), i); }
步骤2:自定义Comparator排序Object数组
这里假设你的hits[]数组里的元素是自定义的业务类(比如叫Hit),这个类里有一个方法能获取到和参考列表元素对应的字段(比如getTargetValue()返回Double类型)。如果你的hits是纯Object数组,需要先做类型转换:
Arrays.sort(hits, new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { // 把Object转换为你的实际业务类型(这里用Hit举例,替换成你的类) Hit hit1 = (Hit) o1; Hit hit2 = (Hit) o2; // 获取两个元素对应的、用于匹配参考列表的值 Double value1 = hit1.getTargetValue(); Double value2 = hit2.getTargetValue(); // 从映射中获取它们在参考列表中的索引 Integer index1 = valueToIndexMap.get(value1); Integer index2 = valueToIndexMap.get(value2); // 处理元素不在参考列表中的情况:这里把这类元素放到排序的末尾 if (index1 == null) index1 = Integer.MAX_VALUE; if (index2 == null) index2 = Integer.MAX_VALUE; // 升序排序:参考列表中靠前的元素,在hits数组里也靠前 // 如果要降序,就改成 return index2.compareTo(index1); return index1.compareTo(index2); } });
关键说明
- 类型匹配:一定要保证
Comparator的泛型和hits[]的元素类型一致——如果是Object数组,就用Comparator<Object>,再在方法内转成实际类型;如果hits是泛型数组(比如Hit[]),可以直接用Comparator<Hit>,更安全。 - 边界处理:如果
hits里有元素对应的值不在参考列表里,上面的代码会把它们放到最后,你可以根据需求调整(比如放到最前,或者抛出异常)。 - 效率优化:用Map做索引映射把每次查找的时间从O(n)降到O(1),排序的整体时间复杂度保持在O(m log m)(m是hits数组的长度),比直接用
indexOf高效得多。
内容的提问来源于stack exchange,提问作者alexbako
相关产品推荐
相关产品推荐

