根据相关的ID列表重新排序集合

时间:2012-05-29 15:24:20

标签: java collections sequence

我有一个具有 id 属性的对象的Collection(无序),以及一个(有序的) id 列表。 ID列表未排序。我想在我的Collection中创建一个对象列表,根据ID列表进行排序。

我没有在Guava或Apache Commons中看到这种方法 - 但这正是我正在寻找的。具有良好实现的库函数。

6 个答案:

答案 0 :(得分: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

就是这样。什么都没有。 (披露:我向Guava捐款。)

或者,如果您知道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));

答案 1 :(得分:1)

如果您的无序输入不比Collection更具体,并且您的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);
    }
}

答案 2 :(得分:0)

听起来你有一个你想要的订单,可能会或可能不会在数字上升/下降?

我建议在下面制作你自己的谓词。 org.apache.commons.collections.CollectionUtils.find(java.util.Collection collection,                                     Predicate predicate);

并遍历您的特定排序,查找无序列表中的每个实际对象。 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

答案 3 :(得分:0)

阅读ID列表,将ID以ID List顺序复制到新列表中。

答案 4 :(得分:0)

创建一个实现Comparable的类。在该类中,根据您的有序ID列表进行排序。然后基于Comparable类定义TreeSet。一个非常简化的例子如下所示。

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

然后,定义并填充您的集合,如下所示:

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

当你执行mySet.add()时,它会根据你的MySort类自动排序。如果迭代生成的TreeSet,则“17”​​条目将出现在“12”条目之前。

答案 5 :(得分:0)

你可以:

使用第一个解决方案,您必须修改您的对象,第二个解决方案是您必须创建另一个类,但您可以保持对象不被修改。 <T>是您的对象类。