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

Posted

技术标签:

【中文标题】根据字符串数组顺序对 ArrayList 重新排序 - Java【英文标题】:Re-order ArrayList Based on String Array's Order - Java 【发布时间】:2014-10-19 08:51:05 【问题描述】:

我有一个数组列表和一个字符串数组。 String 数组包含 ID,Array List 包含 ID 和与这些 ID 相关的信息。此 ArrayList 的顺序不理想。我有一个 Id 的字符串数组,按照我希望它们在 ArrayList 中的顺序排列。

半伪代码示例:

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 数组的目的是什么?你真的需要它还是“只是”对列表进行排序? 我正在使用一个库,它获取我的 id 并根据许多因素对它们进行排序,以特定顺序生成 ID 字符串数组。然后我需要重新排序我的数组列表(其中包含链接到每个 id 的所有信息)以匹配此顺序。 啊哈——酷。太糟糕了,图书馆不能接受一个对象...... 虽然您仍然需要 Comparator 来进行排序(如在各种答案中),但请使用 Map 而不是一堆数组。 【参考方案1】:

一种解决方案是遍历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]

【讨论】:

【参考方案2】:

您可以根据数组中的索引编写自己的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));

【讨论】:

【参考方案3】:

你只需要一个比较器:

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&lt;String, Integer&gt;,其中包含每个 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()));
    
);

【讨论】:

【参考方案4】:

crs_rawStepSeqNum:你的数组列表crs_rawStepSeqNum:相同的数组列表

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;
        
    

【讨论】:

这是如何工作的?你能通过代码来解释它的实际作用吗?

以上是关于根据字符串数组顺序对 ArrayList 重新排序 - Java的主要内容,如果未能解决你的问题,请参考以下文章

按字母顺序对对象的 ArrayList 进行排序

按字母顺序排序arraylist(不区分大小写)

对混合整数和字符串的 ArrayList 进行排序,同时保留字符串和整数的相对顺序

如何根据 array[0] 元素对数组的 ArrayList 进行排序,该元素是以 dd/mm/yyyy 格式给出的日期?

C# ArrayList的排序

根据字符串属性按字母顺序对对象数组进行排序