简体   繁体   English

从List中删除范围(尾部)

[英]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. 不幸的是,我没有看到ListLinkedList任何方法一次性删除所有最后的元素。

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: 实际上, subListJavadoc 特别推荐了这个成语:

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()返回原始列表的视图 ,这意味着:

  1. Any modification done to the view will be reflected in the original list 对视图所做的任何修改都将反映在原始列表中
  2. The returned list is not a 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM