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

本文比较了Java中ArrayList、Vector、Stack与LinkedList的性能差异,详细分析了这些List实现在添加、删除、插入、索引访问等方面的不同表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Quotes: http://www.lifevv.com/java/doc/20071128113711402.html

 

Java Collections Framework的List集合类主要有ArrayList,LinkedList,Vector,Stack等。本文主要对它们作一个比较,说明它们的异同点以及性能上的区别等。


概要
我们在 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      好           好               好                   差              极优    

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

代码
  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. }  
package com.test.collection;

import java.util.Iterator;
import java.util.List;

public class TestList {

    /**
     * List集合性能测试类
     * Usage: java com.test.collection.TestList ListClassName MAX_TIMES
     * 例:java com.test.collection.TestList LinkedList 100000
     */
    public static void main(String[] args) {
        
        if (args != null && args.length == 2) {
            testList(args[0], Integer.parseInt(args[1]));
        } else {
            testList("LinkedList", 20000);
                        
            testList("ArrayList", 20000);
        }
    }
    
    private static void testList(String listName, int maxElements) {
        List list = null;
        try {
            list = (List) Class.forName("java.util." + listName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        addElement2List(list, maxElements);
        deleteElement2List(list);
        insertElement2List(list, maxElements);
        getListElementByIndex(list);
        getListElementByIterator(list);
    }
    
    //add elements to List
    private static void addElement2List(List list, int maxElements) {
        long start = System.currentTimeMillis();

        for (int i = 1; i < maxElements; i++) {
            list.add(new Integer(i));
        }

        long end = System.currentTimeMillis();
        
        
        printTime(list, end-start, " [add] ");
    }
    
    
    //remove elements from List
    private static void deleteElement2List(List list) {
        long start = System.currentTimeMillis();

        while (!list.isEmpty()) {
            list.remove(0);
        }

        long end = System.currentTimeMillis();
        
        
        printTime(list, end-start, " [delete] ");
    }
    
    
    //insert elements to List
    private static void insertElement2List(List list, int maxElements) {
        long start = System.currentTimeMillis();

        for (int i = 1; i < maxElements; i++) {
            list.add(0, new Integer(i));
        }

        long end = System.currentTimeMillis();
        
        
        printTime(list, end-start, " [insert] ");
    }
    
    private static void getListElementByIndex(List list) {
        long start = System.currentTimeMillis();

        for (int i = 1; i < list.size(); i++) {
            Integer ele = (Integer)list.get(i);
        }

        long end = System.currentTimeMillis();
        
        
        printTime(list, end-start, " [index] ");
    }
    
    private static void getListElementByIterator(List list) {
        long start = System.currentTimeMillis();

        Iterator ite = list.iterator();
        while (ite.hasNext()) {
            Integer ele = (Integer)ite.next();
        }

        long end = System.currentTimeMillis();
        
        
        printTime(list, end-start, " [iterator] ");
    }
    
    private static void printTime(List list, long time, String operation) {
        String out = list.getClass().getSimpleName();
        
        out += " " + operation + ": " + time;
        
        System.out.println(out);
    }

}


执行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在删除,插入,迭代取值上有较高的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值