Reordering a collection according to a related list of ids

亡梦爱人 提交于 2019-12-30 12:39:19

问题


I have a Collection (unordered) of objects with an id property, and an (ordered) List of ids. The id list is not sorted. I'd like to create a List of the objects in my Collection, ordered according to the List of ids.

I didn't see a method for this in Guava or Apache Commons - but that's exactly what I'm looking for. A library function with a good implementation.


回答1:


It sounds like your id list has its own order; you're not just using the natural order, right?

Here's the Guava solution:

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

That's it. Nothing to it. (Disclosure: I contribute to Guava.)

Alternately, if you know IDs are unique, it might just say

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));



回答2:


If your unordered input is no more specific than Collection and your List of ids is in an arbitrary order (not decreasing numerically or something like that), your simplest and quite performant approach is probably this. The cost is linear, O(m+n) where m is the number of ids in your initially sorted list and n is the number of values to sort.

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);
    }
}



回答3:


Sounds like you have a given order you want, that may or may not be numerically ascending / descending?

I would recommend making your own Predicate below. org.apache.commons.collections.CollectionUtils.find(java.util.Collection collection, Predicate predicate);

and loop over your specific ordering finding each actual object in the unordered list. N^2 solution

and a creative use of java.util.collections.sort(List list, Comparator c), a org.apache.find(), and java.util.collections.swap(List list, int i, int j) you may get away from n^2




回答4:


Read the List of ID's, copying the Collection into a new List in the ID List order.




回答5:


Create a class that implements Comparable. In that class, do the sorting according to your ordered list of ids. Then define a TreeSet based on the Comparable class. A greatly simplified example is shown below.

e.g.

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()))); 
  }
}

Then, define and populate your set like so:

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

When you do a mySet.add(), it will automatically sort according to your MySort class. If you iterate over the resulting TreeSet, the "17" entry will come before the "12" entry.




回答6:


You can:

  • implement the interface Comparable in your object and then call Collections.sort(List)
  • implement the interface Comparator with a new class and then call Collections.sort(List, Comparator)

With the first solution you have to modify your object, with the second one you have to create another class but you can leave your object unmodified. <T> is your object class.



来源:https://stackoverflow.com/questions/10802096/reordering-a-collection-according-to-a-related-list-of-ids

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!