2012-05-29 61 views
1

我有一個ID屬性的對象集合(無序)和ID(有序)列表。 該id列表沒有排序。我想創建我的集合中的對象列表,根據ID列表進行排序。根據ID的相關列表重新排序集合

我沒有在Guava或Apache Commons中看到這種方法 - 但這正是我正在尋找的。具有良好實現的庫函數。

回答

3

這聽起來像你的id列表有它自己的順序;你不僅僅在使用自然順序,對吧?

這裏的番石榴解決方案:

Ordering.explicit(idList) 
    // constructs a "fluent Comparator" that compares elements in the 
    // explicitly specified order 
    .onResultOf(new Function<MyObject, Id>() { 
    public Id apply(MyObject o) { return o.getId(); } 
    }) // make this a Comparator<MyObject> that compares on IDs 
    .sortedCopy(myObjects); // get the sorted copy of the collection 

就是這樣。沒有什麼。 (披露:我貢獻番石榴。)

或者,如果你知道ID都是唯一的,它可能只是說

Map<Id, MyObject> objectsById = 
    Maps.uniqueIndex(myObjects, GET_ID_FUNCTION); // defined elsewhere 
List<MyObject> sortedObjects = Lists.newArrayList(); 
for (Id id : sortedIds) 
    sortedObjects.add(objectsById.get(id)); 
+0

這很有趣,也是我所期待的。 – Eyal

+0

或者,如果您想對輸入列表進行就地排序,只需使用'Collections.sort(list,Ordering.explicit(idList).onResultOf(..))',因爲'Ordering'也是一個'Comparator' 。 –

0

聽起來就像你有一個你想要的訂單,可能或不可能是數字上升/下降?

我會建議在下面製作自己的謂詞。 org.apache.commons.collections.CollectionUtils.find(java.util.Collection collection, Predicatepredicate);

和循環在你的具體順序尋找在無序列表中的每個實際的對象。 N^2的解決方案

和創造性地運用java.util.collections.sort(List list, Comparator c),一個org.apache.find()和java.util.collections.swap(List list, int i, int j)你可能會從N^2

0

遠閱讀ID的列表中,複製收集到一個新的以ID列表順序列出。

0

創建一個實現Comparable的類。在該課程中,根據您的ID排序列表進行排序。然後根據Comparable類定義一個TreeSet。下面顯示了一個非常簡單的例子。

例如,它會自動排序,根據您的MySort類

private Set<MyObject> mySet = new TreeSet<MyObject>; 
mySet.add(new MyObject(12)); 
mySet.add(new MyObject(17)); 

當你做一個mySet.add():

public class MyObject implements Comparable<MyObject> { 
    private Integer id; 

    // a map of IDs to how they are ordered. 
    private static Map<Integer, Integer> idOrder = null; 

    public MyObject(Integer id) { 
     setId(id); 

     if (idOrder == null) { 
      idOrder = new HashMap<Integer, Integer>(); 
      idOrder.put(17, 1); 
      idOrder.put(27, 2); 
      idOrder.put(12, 3); 
      idOrder.put(14, 4); 
     } 
    } 

    public int getId() { 
     return (this.id); 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public int compareTo(MyObject anotherThing) { 
    return (idOrder.get(this.getId()).compareTo(idOrder.get(anotherThing.getId()))); 
    } 
} 

然後,定義和填充你的設置,像這樣。如果遍歷生成的TreeSet,則「17」​​條目將出現在「12」條目之前。

1

如果你的無序輸入不超過集合更具體和你的ID列表中以任意順序(不是數字減少或類似的東西),你最簡單,最高效的方法可能就是這樣。成本是線性的,O(m + n),其中m是最初排序列表中的id數,n是要排序的值數。

Map<IDType, ValueType> keyed = new HashMap<IDType, ValueType>(); 
for (ValueType value : unsortedCollection) { 
    keyed.put(value.getId(), value); 
} 

List<ValueType> sorted = new ArrayList<ValueType>(); 
for (IDType id : sortedIds) { 
    ValueType value = keyed.get(id); 
    if (value != null) { 
     sorted.add(value); 
    } 
} 
+0

這是我的第一個想法,如果我沒有找到清潔劑已經寫在圖書館。它可能是這個或者@Louis建議的。 – Eyal

+1

聽起來像番石榴解決方案也會這樣做。除非性能很重要,否則我會選擇你認爲最可讀的任何東西。 –