我想从列表中取出并删除第一个元素。我可以看到,我有两个选择:
- 第一次接近:**
LinkedList<String> servers = new LinkedList<String>();
....
String firstServerName = servers.removeFirst();
- 第二种方法**
ArrayList<String> servers = new ArrayList<String>();
....
String firstServerName = servers.remove(0);
我的清单里有很多元素。
- 我们应该优先使用哪一个?
- 以上两个有什么区别?从性能上来说,它们在技术上是一样的吗?如果我们有很多元素,那么复杂性是什么?
什么是最有效的方法来做到这一点。
9条答案
按热度按时间8ehkhllq1#
如果在
ArrayList
和LinkedList
类之间比较“先删除”,LinkedList
显然会胜出。从链表中删除一个元素要花费
O(1)
,而对数组(数组列表)执行此操作要花费O(n)
。qjp7pelc2#
您应该使用
LinkedList
。背景:
实际上,
LinkedList#removeFirst
更高效,因为它是在一个双链表上操作的,并且移除第一个元素基本上只包括将其从链表的头部解除链接,并将下一个元素更新为第一个元素(复杂度O(1)
):ArrayList#remove
在内部数组结构上操作,该内部数组结构需要通过在子数组上复制来将所有后续元素向左移动一个位置(复杂度O(n)
):其他答案:
另一方面,
LinkedList#get
操作需要遍历整个列表的一半来检索指定索引处的元素-在最坏的情况下。ArrayList#get
将直接访问指定索引处的元素,因为它是在数组上操作的。我对效率的经验法则是:
add
/remove
操作,则使用LinkedList
(例如:x 1m 10n 1x);add
/remove
相比,如果执行了大量访问操作,则使用ArrayList
。9avjhtql3#
确保你理解了LinkedList和ArrayList的区别。ArrayList是用Array实现的。
LinkedList删除一个元素需要恒定的时间,ArrayList删除第一个元素可能需要线性时间(为了确认我需要检查实现,而不是这里的javaMaven)。
我还认为LinkedList在空间方面更有效,因为ArrayList不会(也不应该)在每次删除一个元素时重新调整数组的大小,所以它会占用比所需更多的空间。
7xllpg7q4#
我认为您需要的是一个
ArrayDeque
(java.util
中一个被不公平地忽略的类),它的removeFirst
方法与LinkedList
一样在O(1)中执行,但它通常表现出ArrayList
更好的空间和时间特性,它被实现为一个数组中的循环队列。你应该很少使用
LinkedList
。我在17年的Java程序员生涯中做过一次,回想起来很后悔。sxpgvts35#
列表.子列表(从索引取整数,从索引取整数)
返回此列表中指定的fromIndex(含)和toIndex(不含)之间的部分的视图。
很适合ArrayList,其中删除第一个元素的复杂度为O(n)。
baubqpgj6#
移除数组列表的第一个元素是O(n),对于链表是O(1),所以我就这么做了.
检查数组列表documentation
size、isEmpty、get、set、iterator和listIterator操作在常数时间内运行。add操作在摊余常数时间内运行,即添加n个元素需要O(n)时间。所有其他操作在线性时间内运行(粗略地说)。与LinkedList实现相比,常数因子较低。
这家伙实际上得到了OpenJDK源代码link
9avjhtql7#
使用链表要快得多。
链接列表
它只会引用节点,因此第一个节点会消失。
数组列表
使用数组列表时,它必须将所有元素移回一个位置,以保持底层数组正确。
nzk0hqpo8#
正如其他人正确指出的那样,在从非常短的列表以外的任何列表中移除第一个元素时,LinkedList比ArrayList更快。
然而,要在它们之间做出选择,需要考虑操作的完整组合。例如,如果您的工作负载为每个第一个元素删除对一百个元素列表进行数百万次索引访问,那么ArrayList总体上会更好。
eit6fx6z9#
第三种方法
它由java.util.Queue接口公开,LinkedList是该接口的一个实现。
Queue接口公开了E poll()方法,该方法有效地删除了List(Queue)的头部。
在性能方面,poll()方法可以与removeFirst()方法相媲美,但实际上它在幕后使用了removeFirst()方法。