[英]Efficient way to get/remove first element from the list?
我想从列表中取出并删除第一个元素。 我可以看到,我有两个选择:
第一种方法:
LinkedList<String> servers = new LinkedList<String>();
....
String firstServerName = servers.removeFirst();
第二种方法
ArrayList<String> servers = new ArrayList<String>();
....
String firstServerName = servers.remove(0);
我的列表中有很多元素。
什么是最有效的方法来做到这一点。
如果“先删除”的比较是在ArrayList
和LinkedList
类之间进行,则LinkedList
明显胜出。
从链表中删除元素的成本为O(1)
,而对数组(数组列表)执行此操作的成本为O(n)
。
确保您了解 LinkedList 和 ArrayList 之间的区别。 ArrayList 是使用 Array 实现的。
LinkedList 需要恒定的时间来删除元素。 ArrayList 可能需要线性时间来删除第一个元素(确认我需要检查实现,而不是这里的 java 专家)。
另外我认为 LinkedList 在空间方面更有效。 因为 ArrayList 不会(也不应该)在每次删除元素时重新调整数组的大小,所以它占用的空间比需要的多。
实际上, LinkedList#removeFirst
效率更高,因为它在双向链表上运行,并且删除第一个元素基本上只是将它与列表的头部断开链接并将下一个元素更新为第一个:
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
ArrayList#remove
正在对内部数组进行操作,该数组需要通过复制子数组将所有后续元素向左移动一个位置:
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
另一方面, LinkedList#get
操作需要遍历整个列表的一半以检索指定索引处的元素 - 在最坏的情况下。 ArrayList#get
将直接访问指定索引处的元素,因为它对数组进行操作。
我在这里提高效率的经验法则是:
get
)相比,您做了很多add
/ remove
操作,请使用LinkedList
;add
/ remove
相比,如果您执行大量检索操作,请使用ArrayList
。我认为你需要的是一个ArrayDeque
( java.util
一个被不公平地忽视的类)。 它的removeFirst
方法与LinkedList
一样在 O(1) 中执行,而它通常显示出ArrayList
更好的空间和时间特性。 它被实现为数组中的循环队列。
您应该很少使用LinkedList
。 我在 17 年的 Java 程序员生涯中做过一次,现在回想起来很后悔。
List.subList (int fromIndex, int toIndex)
返回此列表中指定的 fromIndex(包括)和 toIndex(不包括在内)之间的部分的视图。
非常适合用于ArrayList ,其中删除第一个元素的复杂度为 O(n)。
final String firstServerName = servers.get(0);
servers = servers.subList(1, servers.size());
使用链表要快得多。
链表
它只会引用节点,因此第一个节点会消失。
数组列表
对于数组列表,它必须将所有元素移回一个位置以保持底层数组正确。
正如其他人正确指出的那样,LinkedList 比 ArrayList 更快,可以从非常短的列表以外的任何内容中删除第一个元素。
但是,要在它们之间做出选择,您需要考虑完整的操作组合。 例如,如果您的工作负载在每次删除第一个元素时对一百个元素列表进行数百万次索引访问,则 ArrayList 总体上会更好。
第三个方法。
它由 java.util.Queue 接口公开。 LinkedList 是这个接口的一个实现。
Queue 接口公开了 E poll() 方法,该方法有效地删除了列表(队列)的头部。
在性能方面, poll() 方法与 removeFirst() 相当。 实际上它在幕后使用 removeFirst() 方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.