我想取出并删除List中的第一个元素。我可以看到,我有两个选择:
第一种方法:
ArrayList<String> servers = new ArrayList<String>();
....
String firstServerName = servers.remove(0);
第二种方法
...
<beans>
<bean id="serviceFactory" class="com.example.MyServiceFactory" />
<bean id="myAction" class="com.example.MyAction" scope="request">
<aop:scoped-proxy/>
</bean>
<bean id="myService" class="com.example.MyService" factory-bean="serviceFactory" factory-method="getService">
<constructor-arg type="java.lang.String" value="myServiceConfig" />
</bean>
</beans>
...
我的列表中有很多元素。
最有效的方法是什么。
答案 0 :(得分:5)
如果比较&#34;首先删除&#34;在ArrayList
和LinkedList
类之间,LinkedList
明显胜出。
从链接列表中删除元素需花费O(1)
,而对阵列(数组列表)执行此操作需要花费O(n)
。
答案 1 :(得分:5)
确保您了解LinkedList和ArrayList之间的区别。 ArrayList使用Array实现。
LinkedList需要一段时间来删除元素。 ArrayList可能需要线性时间来删除第一个元素(以确认我需要检查实现,而不是java专家)。
另外我认为LinkedList在空间方面更有效率。因为每次删除元素时,ArrayList都不会(也不应该)重新调整数组的大小,因此它占用的空间比所需的空间大。
答案 2 :(得分:4)
实际上,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
将直接访问指定索引处的元素,因为它在数组上运行。
我对此提高效率的经验法则是:
LinkedList
/ add
,请使用remove
检索操作(例如:get
); ArrayList
检索操作与add
/ remove
相比较。答案 3 :(得分:3)
使用链表要快得多。
<强>链表强>
它只会引用节点,因此第一个节点消失。
<强>的ArrayList 强>
使用数组列表,它必须将所有元素移回一个位置以保持底层数组正确。
答案 4 :(得分:3)
删除ArrayList的第一个元素是O(n)。因为链接列表是O(1),所以我将使用它。
检查ArrayList documentation
运行size,isEmpty,get,set,iterator和listIterator操作 在恒定的时间。添加操作以分摊的常量时间运行, 也就是说,添加n个元素需要O(n)时间。 所有其他人 操作以线性时间运行(粗略地说)。不变因素 与LinkedList实现相比较低。
这些家伙实际上得到了OpenJDK来源link
答案 5 :(得分:3)
正如其他人正确指出的那样,LinkedList比ArrayList更快,可以从非常短的列表中删除第一个元素。
但是,要在它们之间做出选择,您需要考虑完整的操作组合。例如,如果您的工作负载为每个第一个元素删除对数百个元素列表进行了数百万次索引访问,那么ArrayList总体上会更好。
答案 6 :(得分:3)
我认为你需要的是一个ArrayDeque
(java.util
中一个被不公平忽视的课程)。其removeFirst
方法在O(1)中与LinkedList
一样执行,而它通常显示ArrayList
的更好的空间和时间特征。它被实现为数组中的循环队列。
您应该很少使用LinkedList
。在我作为Java程序员的17年里,我做了一次,回想起来后悔了。
答案 7 :(得分:2)
如果ArrayList删除第一个元素的复杂度为O(n),那么作为替代方法,您可以获得第一个元素而不是删除它只是调用 List.subList(int fromIndex, int toIndex):
final String firstServerName = servers.get(0);
servers = servers.subList(1, servers.size());
答案 8 :(得分:1)
第三条建议。
它由java.util.Queue接口公开。 LinkedList是此接口的实现。
Queue接口正在公开E poll()方法,它有效地删除了List(队列)的头部。
就性能而言,poll()方法与removeFirst()相当。实际上它是在引擎盖下使用removeFirst()方法。