我有整数ID列表。让我们说这个列表是ArrayList<Integer>
或int [],没关系。我有另一个ArrayList<Obj>
包含具有相同ID的对象,如第一个列表中所示,但它们按不同顺序排序。
我想按顺序将第二个列表中的对象排序为第一个列表中的ID。
示例:
FIRST LIST: { 1, 5, 4, 8, 6 }
SECOND LIST: { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] }
RESULT LIST: { Obj[id=1], Obj[id=5], Obj[id=4], Obj[id=8], Obj[id=6] }
有人可以告诉我一种(有效的)方法吗?
答案 0 :(得分:3)
我建议使用地图:
Map<Integer, Obj> map = new HashMap<Integer, Obj>(secondList.size() * 2);
for (final Obj obj : secondList) {
map.put(obj.id, obj);
}
for (int i = 0; i < secondList.size(); i++) {
secondList.set(i, map.get(firstList.get(i)));
}
这在O(n)中运行,恕我直言,这是你能得到的最好的。
答案 1 :(得分:1)
A /创建匹配的id索引列表,例如:
1 -> 0
5 -> 1
4 -> 2
8 -> 3
6 -> 4
这是你的第一个清单的反向参考。它表示每个id的位置。 SparseIntArray是一种很好的方法:
SparseIntArray ref = new SparseIntArray();
for (int i = 0; i < firstList.size(); i++) {
ref.append(firstList.get(i), i);
}
然后你需要使用一个使用Object和ref表的id的Comparator对你的第二个列表进行排序:
Collections.sort(secondList, new Comparator<Obj>() {
public int compare(Obj t1, Obj t2) {
return ref.get(t1.id) - ref.get(t2.id);
}
});
答案 2 :(得分:0)
当他发布时,我正在写Etienne的答案,所以只是为了好玩这里是一个O(N ^ 2)解决方案,其中一个较小的常数因子不会产生任何对象:
int[] first = { 1, 5, 4, 8, 6 };
Obj[] second = { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] };
int i = 0;
while(i < second.length) {
int ind = -1;
for(int j=0;j<first.length;j+=1) {
if(first[j] == second[i].id) {
ind = j;
break;
}
}
if(ind == -1) break; //Bad news
if(ind == i) {
i += 1;
} else {
Obj temp = second[i];
second[i] = second[ind];
second[ind] = temp;
}
}
显然,第二个[]的创建是伪代码,但如果数组长度相等则其余的将起作用。我认为对于非常小的数据集,这将比Etienne快一点,但你必须分析两个答案。