ArrayList、LinkedList、Vector、Stack区别

1,064 阅读2分钟

先说List

  • List存储对象可重复,与Set对立,Set不可重复
  • List与Set都继承Collection接口

提前说结论

  • ArrayList (动态数组),所以查询快,增删慢,线程同步不安全
  • LinkedList(双向链表),查询慢,增删快
  • Vector(动态数组),crud都慢,被ArrayList替代。线程异步安全
  • Stack(堆栈),继承于Vector,先进后出

List基本操作

  • 插入 add()
  • 查找 get()
  • 删除 remove(int index)
  • 修改 set()
  • 清空 clear()
  • 遍历 Iterator

针对性能使用java代码测试

import java.util.ArrayList;
import java.util.LinkedList;

public class TestStack {
    public static void main(String[] args) {
        testArrayList();
        testLinkedList();
        /*  执行结果
        ArrayList add cost time :37901
        ArrayList get cost time :0
        ArrayList remove cost time :37149
        LinkedList add cost time :16
        LinkedList get cost time :1436
        LinkedList remove cost time :0  
        */
    }
    private static void testArrayList(){
        ArrayList<String> list=new ArrayList<String>();
        int maxTestCount=80*10000;
        //测试添加
        long start =System.currentTimeMillis();
        for(int i =0;i<maxTestCount;i++){
            list.add(0,String.valueOf(i));
        }
        long end =System.currentTimeMillis();
        System.out.println("ArrayList add cost time :"+(end-start));//5100
        //测试查询
        start =System.currentTimeMillis();
        for(int i =0;i<maxTestCount;i++){
            list.get(i);
        }
        end =System.currentTimeMillis();
        System.out.println("ArrayList get cost time :"+(end-start));//15
        //测试删除
        start =System.currentTimeMillis();
        for(int i =maxTestCount;i>0;i--){
            list.remove(0);
        }
        end =System.currentTimeMillis();
        System.out.println("ArrayList remove cost time :"+(end-start));//5800
    }
    private static void testLinkedList(){
        LinkedList<String> list=new LinkedList<String>();
        int maxTestCount=50000;
        //测试添加
        long start =System.currentTimeMillis();
        for(int i =0;i<maxTestCount;i++){
            list.add(0,String.valueOf(i));
        }
        long end =System.currentTimeMillis();
        System.out.println("LinkedList add cost time :"+(end-start));//1500
        //测试查询
        start =System.currentTimeMillis();
        for(int i =0;i<maxTestCount;i++){
            list.get(i);
        }
        end =System.currentTimeMillis();
        System.out.println("LinkedList get cost time :"+(end-start));//1500
        //测试删除
        start =System.currentTimeMillis();
        for(int i =maxTestCount;i>0;i--){
            list.remove(0);
        }
        end =System.currentTimeMillis();
        System.out.println("LinkedList remove cost time :"+(end-start));
    }
}

ArrayList添加元素的原理

ArrayList是一个可变长数组,插入数据时,则需要先将原始数组中的数据复制到一个新的数组,随后再将数据赋值到新数组的指定位置(如下图);删除数据时,也是将原始数组中要保留的数据复制到一个新的数组

avatar

LinkedList添加元素的原理

既然LinkedList是一个由相互引用的节点组成的双向链表,那么当把数据插入至该链表某个位置时,该数据就会被组装成一个新的节点,随后只需改变链表中对应的两个节点之间的引用关系,使它们指向新节点,即可完成插入(如下图);同样的道理,删除数据时,只需删除对应节点的引用即可。

avatar

因此,在添加或删除数据的时候,ArrayList经常需要复制数据到新的数组,而LinkedList只需改变节点之间的引用关系,这就是LinkedList在添加和删除数据的时候通常比ArrayList要快的原因