Reordering a collection according to a related list of ids

后端 未结 6 1469
一向
一向 2021-01-16 06:52

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 crea

相关标签:
6条回答
  • 2021-01-16 07:09

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

    0 讨论(0)
  • 2021-01-16 07:10

    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.

    0 讨论(0)
  • 2021-01-16 07:13

    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));
    
    0 讨论(0)
  • 2021-01-16 07:22

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-16 07:29

    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

    0 讨论(0)
  • 2021-01-16 07:34

    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.

    0 讨论(0)
提交回复
热议问题