方法一(先提取索引,再构造新列表)
如果你可以改变数据格式并使用自定义对象,我推荐使用方法2。
您可以先将at中原始元素的索引提取到数组sortedIndices中。如果列表已排序,则值为[1, 2, 3, ..., n-1]。如果需要交换前两个元素,则值为[1, 0, 2, 3, ..., n-1]。之后,您可以根据存储的位置sortedIndices[i]添加元素来构造和填充两个排序列表(btSorted/prcSorted)。
ArrayList<Integer> at = new ArrayList<>(Arrays.asList(2, 0, 2, 3, 4));
ArrayList<Integer> bt = new ArrayList<>(Arrays.asList(2, 1, 3, 5, 4));
ArrayList<String> prc = new ArrayList<>(Arrays.asList("p1", "p2", "p3", "p4", "p5"));
// get indexes of a sorted 'at' list
int[] sortedIndices = IntStream.range(0, at.size())
.boxed().sorted(Comparator.comparing(at::get))
.mapToInt(x -> x).toArray();
// sort 'bt' according to 'at'
ArrayList<Integer> btSorted = new ArrayList<>();
for (int i = 0; i < sortedIndices.length; i++) {
btSorted.add(bt.get(sortedIndices[i]));
}
// sort 'prc' according to 'at'
ArrayList<String> prcSorted = new ArrayList<>();
for (int i = 0; i < sortedIndices.length; i++) {
prcSorted.add(prc.get(sortedIndices[i]));
}
// sort 'at' directly (just for inspection)
ArrayList<Integer> atSorted = new ArrayList<>(at);
Collections.sort(atSorted);
System.out.println("idx: " + Arrays.toString(sortedIndices));
System.out.println("at: " + at + " => " + atSorted);
System.out.println("bt: " + bt + " => " + btSorted);
System.out.println("prc: " + prc + " => " + prcSorted);
输出:
idx: [1, 0, 2, 3, 4]
at: [2, 0, 2, 3, 4] => [0, 2, 2, 3, 4]
bt: [2, 1, 3, 5, 4] => [1, 2, 3, 5, 4]
prc: [p1, p2, p3, p4, p5] => [p2, p1, p3, p4, p5]
方法2 (自定义类和Comparator)
更具可读性将数据存储在自定义类中(例如DataEntry)。然后,您可以轻松地对对象数组(例如data)进行排序,而无需求助于难以阅读的代码:
ArrayList<DataEntry> data = new ArrayList<>();
data.add(new DataEntry(2, 2, "p1"));
data.add(new DataEntry(0, 1, "p2"));
data.add(new DataEntry(2, 3, "p3"));
data.add(new DataEntry(3, 5, "p4"));
data.add(new DataEntry(4, 4, "p5"));
// sort data by 'at'
data.sort(Comparator.comparing(d -> d.at));
// print result
data.forEach(d -> System.out.println(d.at + ", " + d.bt + ", " + d.prc));
输出:
0, 1, p2
2, 2, p1
2, 3, p3
3, 5, p4
4, 4, p5
DataEntry类供参考:
static class DataEntry {
int at;
int bt;
String prc;
public DataEntry(int at, int bt, String prc) {
this.at = at;
this.bt = bt;
this.prc = prc;
}
}
方法 3 (使用 indexOf 和 Comparator)
这只有在要排序的列表中没有重复项 (bt/prc) 时才稳定,因为 indexOf 总是返回列表中指定元素第一次出现的索引 (或 -1)。
可以使用自定义Comparator 和indexOf 对列表进行排序。我们可以在其他列表(bt/prc)中引用当前被比较元素(d)的相应位置的at中的值,以便对它们进行排序:
ArrayList<Integer> at = new ArrayList<>(Arrays.asList(2, 0, 2, 3, 4));
ArrayList<Integer> bt = new ArrayList<>(Arrays.asList(2, 1, 3, 5, 4));
ArrayList<String> prc = new ArrayList<>(Arrays.asList("p1", "p2", "p3", "p4", "p5"));
// sort 'bt' according to 'at'
ArrayList<Integer> btSorted = new ArrayList<>(bt);
btSorted.sort(Comparator.comparing(d -> at.get(bt.indexOf(d))));
// sort prc according to 'at'
ArrayList<String> prcSorted = new ArrayList<>(prc);
prcSorted.sort(Comparator.comparing(d -> at.get(prc.indexOf(d))));
// sort 'at' (just for inspection)
ArrayList<Integer> atSorted = new ArrayList<>(at);
Collections.sort(atSorted);
// print result
System.out.println(at + " => " + atSorted);
System.out.println(bt + " => " + btSorted);
System.out.println(prc + " => " + prcSorted);
输出:
at: [2, 0, 2, 3, 4] => [0, 2, 2, 3, 4]
bt: [2, 1, 3, 5, 4] => [1, 2, 3, 5, 4]
prc: [p1, p2, p3, p4, p5] => [p2, p1, p3, p4, p5]