是否有一种有效的方法可以从List
中移除范围 - 例如尾部 - X元素,例如Java中的LinkedList
?
显然可以逐个删除最后的元素,这应该导致O(X)级别的性能。至少对于LinkedList
个实例,应该可以具有O(1)性能(通过设置要移除的第一个元素周围的引用并设置头/尾引用)。遗憾的是,我在List
或LinkedList
中没有看到任何方法同时删除所有最后一个元素。
目前我正在考虑使用List.subList()
替换列表,但我不确定它是否具有相同的性能。至少在代码中会更清楚,另一方面,我会失去LinkedList
提供的附加功能。
我主要使用List作为堆栈,LinkedList
似乎是最好的选择,至少在语义上是这样。
答案 0 :(得分:58)
subList(list.size() - N, list.size()).clear()
是删除最后N
元素的推荐方法。实际上,Javadoc for subList
具体推荐这个成语:
此方法消除了对显式范围操作的需要(对于数组通常存在的排序)。任何需要列表的操作都可以通过传递subList视图而不是整个列表来用作范围操作。例如,以下习语从列表中删除了一系列元素:
list.subList(from, to).clear();
事实上,我怀疑这个成语可能更多有效(尽管是一个常数因素)而不是调用removeLast()
N
次,只是因为一旦它找到{{从倒数第二个节点开始,它只需要更新链表中的常量指针数,而不是一次更新一个最后N
个节点的指针。
答案 1 :(得分:12)
请注意subList()
会返回原始列表的视图,这意味着:
LinkedList
- 它是List
的内部实现,不可序列化无论如何,使用removeFirst()
或removeLast()
应该足够有效,因为在Java中弹出链表的第一个或最后一个元素是O(1)
操作 - 在内部,{{1保存指向列表两端的指针,删除任何一个就像将指针移动一个位置一样简单。
要一次性移除LinkedList
个元素,您m
的{{1}}性能会受到O(m)
的影响,但奇怪的是,LinkedList
可能是更好的选择,因为删除ArrayList
末尾的元素就像将索引指针(表示数组的末尾)向左移动一个位置一样简单,并且没有像{{1}那样悬挂垃圾节点}。最佳选择?试试这两种方法,对它们进行描述并让数字说明一切。