我有一个对象列表,将进行大量添加/删除。我希望根据特定功能对列表进行排序。
现在,每次添加新对象时,我都会这样做:
list.add(obj1);
Collections.sort(list1, comparator);
删除对象不会“取消排序”列表,因此我只需要对添加操作进行此操作。
但是,Collections.sort
是O(> N),不是很快。
java中是否有任何结构可以让我从一开始就保留排序列表?
忘记提及
我尝试使用TreeSet
。它允许我通过一个比较器,该比较器将用于排序,但也将用于删除不是我想要的元素。我希望对它进行排序,但删除功能与列表相同。
答案 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)
您不能在“正确的”位置添加对象吗?已经排序?
您说过,每次添加新对象时,都会对列表/集合进行排序。
也许您可以使用二进制搜索来找到插入新值所需的确切索引,或者使用比较器来查找。