对于我目前正在开发的Java应用程序,我使用的是ID系统,每个ID都是唯一的字符串。我有两个数组列表,一个是ArrayList<String>
,它只按正确的顺序保存ID,另一个是对象的数组列表,它们都有.ID字段。订购数组对象列表的最佳方法是什么,以使它们的ID与字符串ID的数组列表的顺序相同?
答案 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就可以了。
不可否认,这对你要做的事情做了很多假设。如果这不能达到你想要的效果,你可能应该在你的问题中更具体一些。你想要实现的目标。