从头开始对列表进行排序

时间:2018-11-13 16:21:40

标签: java list sorting

我有一个对象列表,将进行大量添加/删除。我希望根据特定功能对列表进行排序。

现在,每次添加新对象时,我都会这样做:

list.add(obj1);
Collections.sort(list1, comparator);

删除对象不会“取消排序”列表,因此我只需要对添加操作进行此操作。

但是,Collections.sort是O(> N),不是很快。

java中是否有任何结构可以让我从一开始就保留排序列表?

忘记提及

我尝试使用TreeSet。它允许我通过一个比较器,该比较器将用于排序,但也将用于删除不是我想要的元素。我希望对它进行排序,但删除功能与列表相同。

2 个答案:

答案 0 :(得分:2)

按照Alencar的建议,使用Collections.binarySearch(yourList, key, comparator)查找正确的插入位置。这比查找整个列表要快得多,因为binarySearch仅需要log2(列表大小)查询即可找到正确的插入位置。

所以,如果您的插入代码是

void sortedInsert(List<T> list, T value, Comparator<T> comparator) {
  int pos=0;
  ListIterator<T> it=list.listIterator();
  while (it.hasNext() && comparator.compare(value, it.next()) < 0) pos ++;
  if (pos < it.previousIndex()) it.previous();
  it.add(value);
}

...一个更快的版本是...

void sortedInsert2(List<T> list, T value, Comparator<T> comparator) {
  int pos = Collections.binarySearch(list, value, comparator);
  if (pos < 0) {
     pos = -pos -1; // returns negatives if not found; see javadoc
  }
  list.insert(value, pos);
}

请注意,差异可能不会太大,因为插入非链接列表需要向上移动元素。因此,如果基础列表是ArrayList,则平均将一半元素复制到右侧以放置新元素会导致每复制O(n)花费额外的时间。而且,如果该列表已链接,您仍然需要支付O(n)的罚款,但是这次执行二进制搜索-在这种情况下,使用第一个版本可能会更好。

请注意,第一个版本使用ListIterator,以防万一您决定使用链接列表。对于ArrayLists,使用list.get(pos)list.add(pos, value)会更容易,但是在迭代链接列表的情况下,这是一个非常糟糕的主意。

答案 1 :(得分:1)

您不能在“正确的”位置添加对象吗?已经排序?

您说过,每次添加新对象时,都会对列表/集合进行排序。

也许您可以使用二进制搜索来找到插入新值所需的确切索引,或者使用比较器来查找。