黑马程序员技术交流社区

标题: ArrayList, Vector, LinkedList的存储性能和特性? [打印本页]

作者: 金曦    时间: 2012-11-2 19:36
标题: ArrayList, Vector, LinkedList的存储性能和特性?
ArrayList, Vector, LinkedList的存储性能和特性是什么?

作者: 小灰灰    时间: 2012-11-2 19:39
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
摘自:百度
作者: 奋斗的青春    时间: 2012-11-2 21:40
本帖最后由 吴愿涛 于 2012-11-2 21:45 编辑

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。
作者: 田建    时间: 2012-11-3 17:00
这3个都是List集合下的,只需要弄清楚他们各自的优势,然后知道在什么时候去用谁,ArrayList底层是数组额数据结构,增删慢,查找快;Vector和ArrayList差不多,只是加了线程同步,这样影响了效率,你仔细看整个集合框架,你会发现实现了线程同步,效率低的都被干掉了;LinkedList底层是链表,增删快,查找慢,因为链表只需要记住前后的元素!弄清了这再分情况使用即可!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2