如何最好地使用一个ArrayList的顺序在Java中订购另一个?

时间:2012-02-23 21:47:09

标签: java arraylist

对于我目前正在开发的Java应用程序,我使用的是ID系统,每个ID都是唯一的字符串。我有两个数组列表,一个是ArrayList<String>,它只按正确的顺序保存ID,另一个是对象的数组列表,它们都有.ID字段。订购数组对象列表的最佳方法是什么,以使它们的ID与字符串ID的数组列表的顺序相同?

6 个答案:

答案 0 :(得分:3)

我使用ID作为键将所有对象放在HashMap中,然后运行第二个ID列表并使用ID和map创建新的对象列表。应该具有2n左右的复杂度 - > n虽然不是资源友好的。

编辑:明确我的意思

List<String> idList;
List<ObjectWithID> objectList;

Map<String, ObjectWithID> helperMap=new HashMap<>();

//first O(n)
for (ObjectWithID o:objectList) {
  helperMap.put(o.ID, o);
}

int i=0;
//second O(n)
for (String id:idList) {
  objectList.set(i,helperMap.get(id));
  i++;
}

假设objectList和idList具有相同的大小和相同的ids / object.IDs分别为

答案 1 :(得分:2)

分配第3个清单。 O(n ^ 2)解决方案是迭代具有有序ID的列表。在这个循环中有另一个循环来查找对象,其ID ==当前ID在第一个循环/列表中找到。提取此项并将其添加到第3个列表:

for (ID in List<ID>)
    for (Item item in List<Item>){
        if (item.ID == ID){
            list3.add(item);
        }
    }

可怕的算法。我建议你设计你的数据结构。使用地图或比较器。

答案 2 :(得分:2)

免责声明:您没有提到为什么需要订购这些条目,但如果只是为了ID匹配目的,您应该重新设计您的应用程序,从一开始就使用HashMap或TreeMap的内容。

这是一个可能的解决方案,准备工作的O(n)复杂度和实际排序的O(n * log(n))复杂度:

class MyEntry {
   public String id;
}

ArrayList<String> idList = new ArrayList<String>();
ArrayList<MyEntry> entryList = new ArrayList<MyEntry>();

final HashMap<String, Integer> index = new HashMap<String, Integer>();

// Match each ID to its index
for (int i = 0; i < idList.size(); ++i) {
    index.put(idList.get(i), i);
}

Collections.sort(entryList, new Comparator<MyEntry>() {
    public int compare(MyEntry o1, MyEntry o2) {
        return index.get(o1.id) - index.get(o2.id);
    }
});

免责声明II:我实际上并没有运行此代码,但应该可以运行...

修改

仅仅为了记录,我在寻找一种方法来对原始条目列表进行排序时过于集中。 对于这个特定的用例,solution proposed by stryba更简单,更快。

只有在未来的要求使得有必要根据其ID快速恢复条目的索引时,我的方法才有利。

答案 3 :(得分:1)

只是一般的想法(没有编译器)

public class MyListComparator implements Comparator<MyObject>{

    private ArrayList<String> ids;

    public MyListComparator(ArrayList<String> ids)
    {
        this.ids = ids;
    }

    @Override
    public int compare(MyObject o1, MyObject o2) {
        Integer i1 = ids.indexOf(o1.id);
        Integer i2 = ids.indexOf(o2.id);
        return i1.compareTo(i2);
    }
}

答案 4 :(得分:1)

存储在2个列表中并不是一个好的设计。如果可能,您可以重构它并存储在地图中。根据您的要求,您可以决定所需的Map实现类型。例如:如果要维护插入顺序,可以使用LinkedHashMap。

如果无法重构/重新设计,您可以使用我编码的以下示例来测试排序功能。首先,我创建了一个带有变量“id”和“name”的Person对象,如下所示:

public class Person {
    private String id;
    private String name;

    /**
     * @return the id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

以下是Main类,其中实现了排序:

public class TwoLists {
    public static void main(String[] args) {
        ArrayList<String> idList = new ArrayList<String>();
        ArrayList<Person> personList = new ArrayList<Person>();

        idList.add("1");
        idList.add("2");
        idList.add("3");
        idList.add("4");

        TwoLists twoLists = new TwoLists();

        personList.add(twoLists.createPerson("4", "Name4"));
        personList.add(twoLists.createPerson("2", "Name2"));
        personList.add(twoLists.createPerson("3", "Name3"));
        personList.add(twoLists.createPerson("1", "Name1"));

        System.out.println("Before Sorting:");
        for(Person person: personList) {
            System.out.println(person.getId());
        }

        Collections.sort(personList, twoLists.new TwoListsComparator(idList));

        System.out.println("After Sorting:");
        for(Person person: personList) {
            System.out.println(person.getId());
        }
    }

    private class TwoListsComparator implements Comparator<Person> {
        ArrayList<String> idList;

        private TwoListsComparator(ArrayList<String> idList) {
            this.idList = idList;
        }

        public int compare(Person person1, Person person2) {
            int index1 = idList.indexOf(person1.getId());
            int index2 = idList.indexOf(person2.getId());

            return Integer.valueOf(index1).compareTo(index2);
        }
    }

    private Person createPerson(String id, String name) {
        Person p = new Person();
        p.setId(id);
        p.setName(name);

        return p;
    }
}

在上面的代码中,我创建了两个列表:一个用于id字符串,另一个用于Person对象。然后我通过将idList传递给比较器并比较索引来对人员列表进行排序。

答案 5 :(得分:0)

为什么不按ID对两个列表单独进行排序。

制作一个比较器,对您的字符串列表进行排序,然后制作另一个比较对象上.ID字段的比较器。单独对两个列表进行排序,只要两个列表都是1比1就可以了。

不可否认,这对你要做的事情做了很多假设。如果这不能达到你想要的效果,你可能应该在你的问题中更具体一些。你想要实现的目标。