[英]Removing range (tail) from a List
Is there an efficient method to remove a range - say the tail - of X elements from a List
, eg LinkedList
in Java? 是否有一种有效的方法可以从
List
删除X元素的范围(例如尾部),例如Java中的LinkedList
?
It is obviously possible to remove the last elements one by one, which should result in O(X) level performance. 显然可以逐个删除最后的元素,这应该导致O(X)级别的性能。 At least for
LinkedList
instances it should be possible to have O(1) performance (by setting the references around the first element to be removed and setting the head/tail references). 至少对于
LinkedList
实例,应该可以具有O(1)性能(通过设置要移除的第一个元素周围的引用并设置头/尾引用)。 Unfortunately I don't see any method within List
or LinkedList
to remove the last elements all at once. 不幸的是,我没有看到
List
或LinkedList
任何方法一次性删除所有最后的元素。
Currently I am thinking of replacing the list by using List.subList()
but I'm not sure if that has equal performance. 目前我正在考虑使用
List.subList()
替换列表,但我不确定它是否具有相同的性能。 At least it would be more clear within the code, on the other hand I would loose the additional functionality that LinkedList
provides. 至少在代码中会更清楚,另一方面,我会放弃
LinkedList
提供的附加功能。
I'm mainly using the List as a stack, for which LinkedList
seems to be the best option, at least regarding semantics. 我主要使用List作为堆栈,
LinkedList
似乎是最好的选择,至少在语义方面。
subList(list.size() - N, list.size()).clear()
is the recommended way to remove the last N
elements. subList(list.size() - N, list.size()).clear()
是删除最后N
元素的推荐方法。 Indeed, the Javadoc for subList
specifically recommends this idiom: 实际上,
subList
的Javadoc 特别推荐了这个成语:
This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays).
此方法消除了对显式范围操作(对于数组通常存在的排序)的需要。 Any operation that expects a list can be used as a range operation by passing a subList view instead of a whole list.
任何需要列表的操作都可以通过传递subList视图而不是整个列表来用作范围操作。 For example, the following idiom removes a range of elements from a list:
例如,以下习语从列表中删除了一系列元素:
list.subList(from, to).clear();
Indeed, I suspect that this idiom might be more efficient (albeit by a constant factor) than calling removeLast()
N
times, just because once it finds the N
th-to-last node, it only needs to update a constant number of pointers in the linked list, rather than updating the pointers of each of the last N
nodes one at a time. 实际上,我怀疑这个成语可能比调用
removeLast()
N
次更有效(尽管是一个常数因素),只是因为一旦它找到N
到倒数的节点,它只需要更新一定数量的指针在链表中,而不是一次更新一个最后N
节点中的每个节点的指针。
Be aware that subList()
returns a view of the original list, meaning: 请注意,
subList()
返回原始列表的视图 ,这意味着:
LinkedList
- it's an inner implementation of List
that's not serializable LinkedList
- 它是List
的内部实现,不可序列化 Anyway, using either removeFirst()
or removeLast()
should be efficient enough, because popping the first or last element of a linked list in Java is an O(1)
operation - internally, LinkedList
holds pointers to both ends of the list and removing either one is as simple as moving a pointer one position. 无论如何,使用
removeFirst()
或removeLast()
应该足够有效,因为在Java中弹出链表的第一个或最后一个元素是一个O(1)
操作 - 在内部, LinkedList
保存指向列表两端的指针并删除任何一个就像将指针移动一个位置一样简单。
For removing m
elements at once, you're stuck with O(m)
performance with a LinkedList
, although strangely enough an ArrayList
might be a better option, because removing elements at the end of an ArrayList
is as simple as moving an index pointer (denoting the end of the array) one position to its left, and no garbage nodes are left dangling as is the case with a LinkedList
. 为了一次性删除
m
元素,你会遇到使用LinkedList
O(m)
性能,尽管奇怪的是, ArrayList
可能是更好的选择,因为删除ArrayList
末尾的元素就像移动索引指针一样简单(表示数组的末尾)左边的一个位置,没有像LinkedList
那样悬挂垃圾节点。 The best choice? 最佳选择? try both approaches, profile them and let the numbers speak for themselves.
尝试两种方法,分析它们并让数字说明一切。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.