1

我有一个具有id属性的对象集合(无序)和一个(有序)列表idsid 列表未排序。我想在我的集合中创建一个对象列表,根据 ID 列表排序。

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

4

6 回答 6

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));
于 2012-05-29T17:15:17.733 回答
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);
    }
}
于 2012-05-30T01:59:37.527 回答
0

听起来你有一个你想要的给定顺序,可能是也可能不是数字升序/降序?

我建议在下面制作自己的谓词。 org.apache.commons.collections.CollectionUtils.find(java.util.Collection collection, 谓词 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

于 2012-05-29T15:47:35.567 回答
0

读取 ID 列表,将集合复制到 ID 列表顺序中的新列表中。

于 2012-05-29T15:48:18.397 回答
0

创建一个实现 Comparable 的类。在该类中,根据您的有序 id 列表进行排序。然后根据 Comparable 类定义一个 TreeSet。下面显示了一个大大简化的示例。

例如

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”条目之前。

于 2012-05-29T15:51:38.160 回答
0

你可以:

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

于 2012-05-29T15:53:16.950 回答