我一直是一个简单使用的人:
List<String> names = new ArrayList<>();
我使用接口作为可移植性的类型名称,这样当我问类似这样的问题时,我就可以修改代码。
LinkedList何时应用于ArrayList,反之亦然?
我一直是一个简单使用的人:
List<String> names = new ArrayList<>();
我使用接口作为可移植性的类型名称,这样当我问类似这样的问题时,我就可以修改代码。
LinkedList何时应用于ArrayList,反之亦然?
当前回答
您可以根据对该特定列表执行的操作的时间复杂性,使用一个而不是另一个。
|---------------------|---------------------|--------------------|------------|
| Operation | ArrayList | LinkedList | Winner |
|---------------------|---------------------|--------------------|------------|
| get(index) | O(1) | O(n) | ArrayList |
| | | n/4 steps in avg | |
|---------------------|---------------------|--------------------|------------|
| add(E) | O(1) | O(1) | LinkedList |
| |---------------------|--------------------| |
| | O(n) in worst case | | |
|---------------------|---------------------|--------------------|------------|
| add(index, E) | O(n) | O(n) | LinkedList |
| | n/2 steps | n/4 steps | |
| |---------------------|--------------------| |
| | | O(1) if index = 0 | |
|---------------------|---------------------|--------------------|------------|
| remove(index, E) | O(n) | O(n) | LinkedList |
| |---------------------|--------------------| |
| | n/2 steps | n/4 steps | |
|---------------------|---------------------|--------------------|------------|
| Iterator.remove() | O(n) | O(1) | LinkedList |
| ListIterator.add() | | | |
|---------------------|---------------------|--------------------|------------|
|--------------------------------------|-----------------------------------|
| ArrayList | LinkedList |
|--------------------------------------|-----------------------------------|
| Allows fast read access | Retrieving element takes O(n) |
|--------------------------------------|-----------------------------------|
| Adding an element require shifting | o(1) [but traversing takes time] |
| all the later elements | |
|--------------------------------------|-----------------------------------|
| To add more elements than capacity |
| new array need to be allocated |
|--------------------------------------|
其他回答
ArrayList和LinkedList都实现了List接口,它们的方法和结果几乎相同。然而,它们之间几乎没有区别,这取决于需求,使一个优于另一个。
阵列列表与链接列表
1) 搜索:与LinkedList搜索操作相比,ArrayList搜索操作非常快。ArrayList中的get(int index)给出了O(1)的性能,而LinkedList的性能为O(n)。
原因:ArrayList为其元素维护基于索引的系统,因为它隐式使用数组数据结构,这使得在列表中搜索元素的速度更快。另一方面,LinkedList实现了双链接列表,这需要遍历所有元素来搜索元素。
2) 删除:LinkedList删除操作提供O(1)性能,而ArrayList提供可变性能:最坏情况下(删除第一个元素时)为O(n),最好情况下(移除最后一个元素时,为O(2)。
结论:LinkedList元素删除速度比阵列列表。
原因:LinkedList的每个元素都有两个指针(地址),指向列表中的两个相邻元素。因此,移除仅需要改变将要移除的节点的两个相邻节点(元素)中的指针位置。当在ArrayList中时,需要移动所有元素以填充移除的元素所创建的空间。
3) 插入性能:LinkedList add方法提供O(1)性能,而ArrayList在最坏情况下提供O(n)性能。原因与删除说明相同。
4) 内存开销:ArrayList维护索引和元素数据,而LinkedList维护相邻节点的元素数据和两个指针
因此LinkedList中的内存消耗相对较高。
这些类之间几乎没有相似之处,如下所示:
ArrayList和LinkedList都是List接口的实现。它们都保持元素插入顺序,这意味着在显示ArrayList和LinkedList元素时,结果集将具有元素插入列表的相同顺序。这两个类都是非同步的,可以使用Collections.synchronizedList方法显式同步。这些类返回的迭代器和listIterator是快速失败的(如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,其他任何方式,迭代器都会抛出ConcurrentModificationException)。
何时使用LinkedList,何时使用ArrayList?
如上所述,与ArrayList(O(n))相比,插入和删除操作在LinkedList中提供了良好的性能(O(1))。因此,若应用程序中需要频繁添加和删除,则LinkedList是最佳选择。搜索(get方法)操作在Arraylist(O(1))中很快,但在LinkedList(O(n))中不快因此,如果添加和删除操作更少,搜索操作需求更多,ArrayList将是您的最佳选择。
除了上面的其他好参数之外,您应该注意到ArrayList实现了RandomAccess接口,而LinkedList实现了Queue。
因此,他们解决的问题略有不同,效率和行为有所不同(见他们的方法列表)。
Joshua Bloch,LinkedList的作者:
有人真的使用LinkedList吗?我写的,我从来没有用过。
链接:https://twitter.com/joshbloch/status/583813919019573248
很抱歉,我的答案没有其他答案那样信息丰富,但我认为这是最不言自明的答案。
ArrayList是您想要的。LinkedList几乎总是一个(性能)bug。
为什么LinkedList很糟糕:
它使用了大量小内存对象,因此影响了整个过程的性能。许多小对象不利于缓存位置。任何索引操作都需要遍历,即具有O(n)性能。这在源代码中并不明显,导致算法O(n)比使用ArrayList时慢。获得好的表现是很棘手的。即使big-O性能与ArrayList相同,它也可能会明显变慢。在源代码中看到LinkedList很刺耳,因为它可能是错误的选择。
我的经验法则是,如果我需要一个集合(即不需要是一个列表),那么如果你事先知道大小,或者可以自信地知道大小,或知道它不会有太大变化,那么就使用ArrayList。如果您需要随机访问(即使用get(index)),请避免LinkedList。基本上,只有当您不需要索引访问并且不知道正在分配的集合的(近似)大小时,才使用LinkedList。此外,如果您要进行大量添加和删除(再次通过Collection接口),则LinkedList可能更可取。