现在的位置: 首页 > 综合 > 正文

ArrayList、Vector和LinkedList

2017年11月20日 ⁄ 综合 ⁄ 共 2577字 ⁄ 字号 评论关闭

IT程序员开发必备-各类资源下载清单,史上最全IT资源,个人收藏总结!

/************************说法1************************/

ArrayList、Vector和LinkedList实现了所有List接口的操作,并允许存储null值。

1.实现方式

ArrayList和Vector是List接口的可变长数组实现,即动态数组(Object类型的数组)。new ArrayList()时,底层会生成一个长度为10的数组来存放对象,如果预先知道list会存放多少个对象的话,最好通过new ArrayList(int length)的方式先确定数组的最小长度,如new ArrayList(50),这样能提高底层的效率。

LinkedList是List接口的双向循环链表实现(这意味这其可以作为堆栈和队列来使用)。

2.性能

ArrayList和Vector创建机制:当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍(指的是当前数组容量的一倍)的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

ArrayList和Vector操作性能:插入/删除一个元素需要将该元素后面的所有元素后移/前移一位,所以插入/删除操作很慢;允许直接按序号索引数组元素,所以遍历查找数据很快。具体解释:ArrayList和Vector中,从指定的位置(用index)检索一个对象,或在集合的末尾插入、删除一个对象的时间是一样的,可表示为O(1)。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?因为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行(n-i)个对象的位移操作。

LinkedList操作性能:插入/删除一个元素只需要用指针记录本项的前后项即可,所以插入/删除操作很快;按序号索引数据需要进行前向或后向遍历,所以遍历查找数据很慢。具体解释:LinkedList中,在插入/删除集合中任何位置的元素所花费的时间都是一样的 --> O(1);它在进行索引一个元素的时候比较慢,为O(i),其中i是索引的位置。补充:在进行插入/删除操作前必须先要遍历查找到操作位置,即访问任意一个索引都要求跨越多个节点。插入/删除操作时除了有跨越多个节点(遍历插入点时需要跨越多个节点)的性能开销之外,还要有另外一个开销,即创建节点对象的开销。这个遍历过程也是要消耗资源的。在优势方面,LinkedList实现的插入和删除操作没有其他开销,因此,插入-删除开销几乎完全依赖于插入-删除点离集合末尾的远近。

3.是否线程安全(是否同步)

ArrayList的全部public方法均未同步。Vector对几乎所有的方法都进行了同步(线程安全,多线程时使用),所以通常性能上较ArrayList差一些。

LinkedList的全部public方法均未同步。

如果要从Java SDK得到一个线程安全的"双向链表",你可以利用一个同步封装器从Collections.synchronizedList(List)得到一个同步封装的LinkedList。然而,使用同步封装器相当于加入了一个间接层,它会带来昂贵的性能代价。当封装器把调用传递给被封装的方法时,每一个方法都需要增加一次额外的方法调用,经过同步封装器封装的方法会比未经封装的方法慢二到三倍。对于象搜索之类的复杂操作,这种间接调用所带来的开销不是很突出;但对于比较简单的方法,比如访问功能或者更新功能,这种开销可能对性能造成严重的影响。

这意味着,和Vector相比,经过同步封装的LinkedList在性能上处于显著的劣势,因为Vector不需要为了线程安全而进行任何额外的间接调用。如果你想要有一个线程安全的"双向链表",你可以复制LinkedList类并让几个必要的方法同步,这样你可以得到一个速度更快的实现。

4.在网上看到一个实测结论:ArrayList和Vector通常比LinkedList和同步封装之后的LinkedList有着更好的性能。即使在你认为LinkedList可能提供更高性能的情况下,你也可以通过修改元素加入的方式从ArrayList争取更好的性能,例如翻转集合元素的次序。 有些情况下LinkedList会有更好的性能,例如,当大量元素需要同时加入到大型集合的开头和末尾时。但一般而言,我建议你优先使用ArrayList/Vector类,只有当它们存在明显的性能问题而LinkedList能够改进性能时,才使用LinkedList。

/**********************说法2************************/

讨论1:

*ArrayList与Vector都是基于数组实现的这就说明ArrayList与Vector适合做遍历而不适合做频繁的插入和删除。
 * vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。

* 如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.
 * 如过在集合中使用数据量比较大的数据,用vector有一定的优势
 * LinkedList是基于链表实现的,所以它生来就是为了频繁插入与删除对象。

讨论2:内存占用 基于数组实现的List,在动态扩展时会产生新的数组,然后把旧数组里的内容复制到新数组里,
 * 这会产生大量的不再被使用的对象引用变量等待系统回收。而基于链表实现的List就不会有这种问题。

* 讨论3:toArray()方法
 * 基于数组实现的List会直接返回一个底层数组的拷贝(使用了System.arraycopy方法),基于链表实现的List会新生成一个数组。

抱歉!评论已关闭.