Java Collections Framework - Java集合框架之List篇 ArrayList与LinkedList等的性能比较

 
概要
我们在 Java Collections Framework - Java集合框架List,Map,Set等全面介绍之概要篇  一文中对Java集合框架(Java Collections Framework)做了一个比较全面的介绍。

该文粗略地介绍了List集合的概念定义等。

List集合
List继承自Collection接口。List是一种有序集合,List中的元素可以根据索引(顺序号:元素在集合中处于的位置信息)进行取得/删除/插入操作。
跟Set集合不同的是,List允许有重复元素。对于满足e1.equals(e2)条件的e1与e2对象元素,可以同时存在于List集合中。当然,也有List的实现类不允许重复元素的存在。
同时,List还提供一个listIterator()方法,返回一个ListIterator接口对象,和Iterator接口相比,ListIterator添加元素的添加,删除,和设定等方法,还能向前或向后遍历。

List跟Collection的关系:
java.util.Collection [I]
+--java.util.List [I]
   +--java.util.ArrayList [C]
   +--java.util.LinkedList [C]
   +--java.util.Vector [C]
      +--java.util.Stack [C]

List接口的实现类主要有ArrayList,LinkedList,Vector,Stack等。

本文主要对上面提到的几个类作一个比较,说明它们的异同点以及性能上的区别等。

ArrayList,LinkedList,Vector,Stack的相同点
ArrayList,LinkedList,Vector,Stack等类都实现了List接口,都属于List集合。
List接口里定义的基本方法是一样的。
public interface List
    extends Collection
{
    //... other Collection methods
    
    //根据索引取得元素
    public abstract Object get(int i);
    //在指定位置(索引)处插入新的元素
    public abstract Object set(int i, Object obj);
    //在List的尾部插入新的元素
    public abstract void add(int i, Object obj);
    //删除指定位置(索引)处的元素
    public abstract Object remove(int i);
    //取得指定对象的最开始的索引位置
    public abstract int indexOf(Object obj);
    //取得指定对象的最后的索引位置
    public abstract int lastIndexOf(Object obj);
    //List提供的新的遍历方法
    public abstract ListIterator listIterator();
    //从指定位置i处开始迭代。最初next()方法返回的将是位置i处的元素。
    public abstract ListIterator listIterator(int i);
    //取得从位置i到j的所有元素(包含i但不包含j位置的元素),返回一个新的集合对象。
    public abstract List subList(int i, int j);
}


ArrayList,LinkedList,Vector,Stack的相异之处:
数据构造上的差异:
ArrayList,Vector,Stack都是使用动态数组来保存集合中的对象元素,亦即ArrayList,Vector,Stack具有基本相似的数据结构。ArrayList,Vector除了以下所说的线程同步上的差异之外,它们的功能基本一样;Vector从Stack继承,除了拥有Stack具有的功能之外,还实现了栈的功能。
而LinkedList则使用链表的形式来保存集合中的对象元素。

线程处理上的差异:
ArrayList,LinkedList没有使用synchronized对线程同步作任何处理,也就是说它们在同一时刻可以由多个线程访问,不是线程安全的;
Vector,Stack则使用synchronized对主要方法作了同步控制,它们在同一时刻只能由一个线程访问。


ArrayList,LinkedList,Vector,Stack的性能比较:
因为数据构造上的差异,它们在处理元素的添加,删除,插入,索引取值,遍历取值方面的效率上也各不相同。
ArrayList,Vector,Stack都是采用动态数组,它们的处理效率基本一样。
LinkedList采用链表构造,所以它跟ArrayList,Vector,Stack在添加,删除,插入,取值操作上就很大差异。
在具体的应用中,为了性能,功能上的考虑,我们可以根据具体的需求采用不同的List。

ArrayList,Vector,Stack


元素添加操作
ArrayList,Vector,Stack添加元素时的基本步骤是:
- 确保动态数组的空间大小。若空间不够时,则为集合元素重新分配空间,新分配的空间是原有空间大小的1.5倍左右,并把原来的集合元素拷贝到新分配的空间上。所以如果对象元素很多,有可能分配的空间大小要远远多出实际的元素,所以为了内存利用效率考虑,使用ArrayList等时,如果事先知道元素的多少,最好初始化时为其分配最大空间。
- 设置新元素到size+1位置。
大量添加时的性能:因为重新分配空间的次数不会太多,性能评价:好
元素删除操作
- 将删除位置i以后的元素全部往前移一个位置
- 设置size处元素为null
大量删除时的性能:因为每个元素的删除都会进行移位拷贝,性能评价:差
元素插入操作
- 同 元素添加操作
- 将插入位置i及以后的所有元素往后移一个位置
- 设置新元素至插入位置i
大量插入时的性能:因为每个元素的插入都会进行移位拷贝,性能评价:差
索引取值/遍历取值
因为是动态数组结构,所以索引取值(根据数组的下标)的速度非常快。
它们的遍历取值(Iterator.next())的内部实现是根据当前元素的位置取得下一个元素,所以跟索引取值一样,都是简单地引用数组的下标,所以速度也非常快。
性能评价:极优

LinkedList


元素添加操作
元素删除操作
元素插入操作

LinkedList的元素添加,删除,插入的操作步骤一样:
- 定位需要操作的元素
- 执行添加,删除,插入操作
虽然在元素的定位操作上需要花些时间,但LinkedList在处理时对元素的定位作了优化,性能评价:好
索引取值
因为LinkedList的链表结构,所以对元素的索引取值是一个遍历的过程,性能评价:极差
遍历取值
LinkedList在遍历的时候保存了当前元素,因为它的链表结构,可以快速的定位下一个元素。性能评价:极优

性能总结:
     -     add()操作     delete()操作      insert操作        index取值操作     iterator取值操作  
ArrayList/Vector/Stack      好           差               差                   极优            极优  
LinkedList      好           好               好                   差              极优    

下面举例来说明它们在性能上的区别。

代码
<script src="/images/code/js/shCore.js" type=text/javascript></script> <script language=javascript> </script> <script src="/images/code/js/shBrushJava.js" type=text/javascript></script>
  1. package com.test.collection;   
  2.   
  3. import java.util.Iterator;   
  4. import java.util.List;   
  5.   
  6. public class TestList {   
  7.   
  8.     /**  
  9.      * List集合性能测试类  
  10.      * Usage: java com.test.collection.TestList ListClassName MAX_TIMES  
  11.      * 例:java com.test.collection.TestList LinkedList 100000  
  12.      */  
  13.     public static void main(String[] args) {   
  14.            
  15.         if (args != null && args.length == 2) {   
  16.             testList(args[0], Integer.parseInt(args[1]));   
  17.         } else {   
  18.             testList("LinkedList"20000);   
  19.                            
  20.             testList("ArrayList"20000);   
  21.         }   
  22.     }   
  23.        
  24.     private static void testList(String listName, int maxElements) {   
  25.         List list = null;   
  26.         try {   
  27.             list = (List) Class.forName("java.util." + listName).newInstance();   
  28.         } catch (Exception e) {   
  29.             e.printStackTrace();   
  30.         }   
  31.            
  32.         addElement2List(list, maxElements);   
  33.         deleteElement2List(list);   
  34.         insertElement2List(list, maxElements);   
  35.         getListElementByIndex(list);   
  36.         getListElementByIterator(list);   
  37.     }   
  38.        
  39.     //add elements to List   
  40.     private static void addElement2List(List list, int maxElements) {   
  41.         long start = System.currentTimeMillis();   
  42.   
  43.         for (int i = 1; i < maxElements; i++) {   
  44.             list.add(new Integer(i));   
  45.         }   
  46.   
  47.         long end = System.currentTimeMillis();   
  48.            
  49.            
  50.         printTime(list, end-start, " [add] ");   
  51.     }   
  52.        
  53.        
  54.     //remove elements from List   
  55.     private static void deleteElement2List(List list) {   
  56.         long start = System.currentTimeMillis();   
  57.   
  58.         while (!list.isEmpty()) {   
  59.             list.remove(0);   
  60.         }   
  61.   
  62.         long end = System.currentTimeMillis();   
  63.            
  64.            
  65.         printTime(list, end-start, " [delete] ");   
  66.     }   
  67.        
  68.        
  69.     //insert elements to List   
  70.     private static void insertElement2List(List list, int maxElements) {   
  71.         long start = System.currentTimeMillis();   
  72.   
  73.         for (int i = 1; i < maxElements; i++) {   
  74.             list.add(0new Integer(i));   
  75.         }   
  76.   
  77.         long end = System.currentTimeMillis();   
  78.            
  79.            
  80.         printTime(list, end-start, " [insert] ");   
  81.     }   
  82.        
  83.     private static void getListElementByIndex(List list) {   
  84.         long start = System.currentTimeMillis();   
  85.   
  86.         for (int i = 1; i < list.size(); i++) {   
  87.             Integer ele = (Integer)list.get(i);   
  88.         }   
  89.   
  90.         long end = System.currentTimeMillis();   
  91.            
  92.            
  93.         printTime(list, end-start, " [index] ");   
  94.     }   
  95.        
  96.     private static void getListElementByIterator(List list) {   
  97.         long start = System.currentTimeMillis();   
  98.   
  99.         Iterator ite = list.iterator();   
  100.         while (ite.hasNext()) {   
  101.             Integer ele = (Integer)ite.next();   
  102.         }   
  103.   
  104.         long end = System.currentTimeMillis();   
  105.            
  106.            
  107.         printTime(list, end-start, " [iterator] ");   
  108.     }   
  109.        
  110.     private static void printTime(List list, long time, String operation) {   
  111.         String out = list.getClass().getSimpleName();   
  112.            
  113.         out += " " + operation + ": " + time;   
  114.            
  115.         System.out.println(out);   
  116.     }   
  117.   
  118. }  


执行Client,输出结果:
C:/test/list>java com.test.collection.TestList ArrayList 100000
ArrayList  [add] : 79
ArrayList  [delete] : 8703
ArrayList  [insert] : 9281
ArrayList  [index] : 0
ArrayList  [iterator] : 16

C:/test/list>java com.test.collection.TestList LinkedList 100000
LinkedList  [add] : 125
LinkedList  [delete] : 16
LinkedList  [insert] : 78
LinkedList  [index] : 80328
LinkedList  [iterator] : 0

C:/test/list>java com.test.collection.TestList Vector 100000
Vector  [add] : 63
Vector  [delete] : 8546
Vector  [insert] : 9422
Vector  [index] : 16
Vector  [iterator] : 0

C:/test/list>java com.test.collection.TestList Stack 100000
Stack  [add] : 47
Stack  [delete] : 8593
Stack  [insert] : 9610
Stack  [index] : 0
Stack  [iterator] : 16

总结:
本文主要比较了ArrayList,Vector,Stack与LinkedList的操作性能。
ArrayList,Vector与Stack在索引取值,迭代取值上有较高的性能。
LinkedList在删除,插入,迭代取值上有较高的性能。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值