根据字符串数组的顺序重新排列ArrayList - Java

6
我有一个ArrayList和一个String数组。String数组包含IDs,而ArrayList包含与这些IDs相关的信息。但是,这个ArrayList的顺序不尽如人意。我有一个String数组,其中按照我想要它们在ArrayList中的顺序存储了这些IDs。
半伪代码示例:
ArrayList<MyObject> myList = new ArrayList<MyObject>();
for (every username)
{
    myList.add(new MyObject(id, username, content, country);
}

String[] ids = new String[myList.size()];
...Ids are added and sorted here...

我现在有一个Id列表,按照正确的顺序排列。 "myList" 中的每个 Id 对应于 "ids" 字符串数组中的一个 Id。我想根据 "ids" 字符串数组中对应的 id 的顺序对 "myList" 进行排序。

我该如何以这种方式重新对我的 ArrayList 进行排序呢?

Eg. if in Array list I have:

1. 123, Bob, test, USA
2. 1234, Vladimir, test, USA
3. 12345, Yoseph, test, USA

and in the String[] I have:

1. 1234
2. 123
3.12345

我该如何根据字符串数组中的Id重新排序ArrayList,从而得到以下结果:
1. 1234, Vladimir, test, USA
2. 123, Bob, test, USA
3. 12345, Yoseph, test, USA

ID数组的目的是什么?你真的需要它还是只是为了对列表进行排序而已? - froderik
我正在使用一个库,它根据许多因素对我的ID进行排序,生成特定顺序的字符串数组。然后,我需要重新对我的ArrayList进行排序(其中包含与每个ID相关联的所有信息),以匹配这个顺序。 - JosephG
啊哈 - 很酷。太遗憾了,这个库不能接受一个对象.... - froderik
1
虽然您仍需要一个比较器来进行排序(就像各种答案中所示),但请使用 Map 而不是一堆数组。请务必这样做。 - user949300
4个回答

6
一种解决方案是遍历“ids”数组,并在对象中搜索当前数组中的“id”。我们知道它的最终(期望)位置:它是数组中的索引(因为我们希望列表按照数组排序),因此我们可以将此元素移动到列表中的最终位置(通过与当前在数组中的位置相同的元素进行交换)。
for (int i = ids.length - 1; i > 0; i--) { // Downward for efficiency
    final String id = ids[i];
    // Big optimization: we don't have to search the full list as the part
    // before i is already sorted and object for id can only be on the remaining
    for (int j = i; j >= 0; j--) // NOTE: loop starting at i
        if (id.equals(myList.get(j).getId()) {
            Collections.swap(myList, j, i);
            break;
        }
}

注意:for循环省略了最后一个元素(i==0),因为如果所有其他元素都在正确的位置上,那么最后一个元素也在正确的位置上。
这比创建比较器并使用排序算法(例如Collections.sort())要快得多,因为元素的顺序已经知道(由ids数组定义),而排序算法(无论算法有多聪明)只能使用比较器返回的[less | equals | greater]信息。

4
你可以基于数组中的索引编写自己的Comparator,具体参见Comparator
public class MyObjectComparator implements Comparator<MyObject> {
    private List<String> ids;

    public MyObjectComparator(String[] ids) {
        this.ids = Arrays.asList(ids); // Copying the array would be safer
    }

    public int compare (MyObject obj1, MyObject obj2) {
        return Integer.compare(ids.indexOf(obj1), ids.indexOf(obj2));
    }
}

// Use it:
Collections.sort (myList, new MyObjectComparator(ids));

1
你只需要一个比较器:
List<String> ids = Arrays.asList(array);
Collections.sort(list, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) { 
        return Integer.compare(ids.indexOf(o1.getId()), ids.indexOf(o2.getId()));
    }
});

当然,如果您的列表很大,这将非常低效。因此,最好构建一个Map<String,Integer>,其中包含每个ID作为键和其在数组中的位置作为值,并在比较器内使用此映射。
Map<String, Integer> idPositions = new HashMap<>();
for (int i = 0; i < array.length; i++) {
    idPositions.put(array[i], i);
}

Collections.sort(list, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) { 
        return idPositions.get(o1.getId()).compareTo(idPositions.get(o2.getId()));
    }
});

0

crs_rawStepSeqNum: 你的ArrayList
crs_rawStepSeqNum: 同一个ArrayList

for(int x =0;x<crs_rawStepSeqNum.size();x++)
    if((x+1) < crs_rawStepSeqNum.size()) {
        if (Integer.parseInt(crs_rawStepSeqNum.get(x)) > Integer.parseInt(crs_rawStepSeqNum.get(x + 1))) {
            crs_rawStepSeqNum.set(x, crs_rawStepSeqNum.get(x + 1));
            crs_rawStepSeqNum.set(x + 1, crs_StepSeqNum.get(x));
            crs_StepSeqNum.clear();
            crs_StepSeqNum.addAll(crs_rawStepSeqNum);
            x=0;
        }
    }
}

这是如何工作的?你能否走一遍代码,解释它实际上在做什么? - GrumpyCrouton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接