从List中删除范围(尾部)

时间:2012-05-29 10:50:56

标签: java list collections stack

是否有一种有效的方法可以从List中移除范围 - 例如尾部 - X元素,例如Java中的LinkedList

显然可以逐个删除最后的元素,这应该导致O(X)级别的性能。至少对于LinkedList个实例,应该可以具有O(1)性能(通过设置要移除的第一个元素周围的引用并设置头/尾引用)。遗憾的是,我在ListLinkedList中没有看到任何方法同时删除所有最后一个元素。

目前我正在考虑使用List.subList() 替换列表,但我不确定它是否具有相同的性能。至少在代码中会更清楚,另一方面,我会失去LinkedList提供的附加功能。

我主要使用List作为堆栈,LinkedList似乎是最好的选择,至少在语义上是这样。

2 个答案:

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

  1. 对视图所做的任何修改都将反映在原始列表中
  2. 返回的列表不是 a LinkedList - 它是List的内部实现,不可序列化
  3. 无论如何,使用removeFirst()removeLast()应该足够有效,因为在Java中弹出链表的第一个或最后一个元素是O(1)操作 - 在内部,{{1保存指向列表两端的指针,删除任何一个就像将指针移动一个位置一样简单。

    要一次性移除LinkedList个元素,您m的{​​{1}}性能会受到O(m)的影响,但奇怪的是,LinkedList可能是更好的选择,因为删除ArrayList末尾的元素就像将索引指针(表示数组的末尾)向左移动一个位置一样简单,并且没有像{{1}那样悬挂垃圾节点}。最佳选择?试试这两种方法,对它们进行描述并让数字说明一切。