• java集合系列——List集合总结(六)


    **一.总结概述 **

    1. List继承了Collection,是有序的列表。
    2. 实现类有ArrayList、LinkedList、Vector、Stack等
    • ArrayList是基于数组实现的,是一个数组队列。可以动态的增加容量!
    • LinkedList是基于链表实现的,是一个双向循环列表。可以被当做堆栈使用!
    • Vector是基于数组实现的,是一个矢量队列,是线程安全的!
    • Stack是基于数组实现的,是栈,它继承与Vector,特性是FILO(先进后出)!

    二.使用场景

    在实际的应用中如果使用到队列,栈,链表,首先可以想到使用List。不同的场景下面使用不同的工具,效率才能更高!

    1. 当集合中对插入元素数据的速度要求不高,但是要求快速访问元素数据,则使用ArrayList!
    2. 当集合中对访问元素数据速度不做要求不高,但是对插入和删除元素数据速度要求高的情况,则使用LinkedList!
      3.当集合中有多线程对集合元素进行操作时候,则使用Vector!但是现在BVector现在一般不再使用,如需在多线程下使用,可以用CopyOnWriteArrayList,在java.util.concurrent包下。
      4.当集合中有需求是希望后保存的数据先读取出来,则使用Stack!

    三.性能测试

    /*
     * @author 阿飞
     * 性能测试,通过插入、随机读取和删除对ArrayList、LinkedList、Vector和Stack进行测试!
     * 结论:看LinkedList
     *  插入10万个元素,LinkedList所花时间最短:17 ms。
     *	删除10万个元素,LinkedList所花时间最短: 9 ms。
     *	遍历10万个元素,LinkedList所花时间最长:10255 ms;而ArrayList、Stack和Vector则相差不多,都只用了几秒。
     *	(1) 对于需要快速插入,删除元素,应该使用LinkedList。
     *  (2) 对于需要快速随机访问元素,应该使用ArrayList。
     * 
     */
    public class ListTest {
    
        private static final int COUNT = 100000; //十万
    
        private static ArrayList<Object> arrayList = new ArrayList<Object>();
        private static LinkedList<Object> linkedList = new LinkedList<Object>();
        private static Vector<Object> vector = new Vector<Object>();
        private static Stack<Object> stack = new Stack<Object>();
    
        public static void main(String[] args) {
            System.out.println("....开始测试插入元素..........");
            
            // 插入元素测试
            insertData(arrayList,"ArrayList") ;
            insertData(linkedList,"LinkedList") ;
            insertData(vector,"Vector") ;
            insertData(stack,"Stack") ;
    
            System.out.println("....开始测试读取元素..........");
       
            // 随机读取元素测试
            readAccessData(arrayList,"ArrayList") ;
            readAccessData(linkedList,"LinkedList") ;
            readAccessData(vector,"Vector") ;
            readAccessData(stack,"Stack") ;
            
            System.out.println("....开始测试删除元素..........");
            
            // 随机读取元素测试
            deleteData(arrayList,"ArrayList") ;
            deleteData(linkedList,"LinkedList") ;
            deleteData(vector,"Vector") ;
            deleteData(stack,"Stack") ;
            
            
            
        }
    
    
        /**
         * 指定的List 的子类中插入元素,并统计插入的时间
         * @param list List 的子类
         * @param name 子类的名称
         */
        private static void insertData(List<Object> list,String name) {
            long startTime = System.currentTimeMillis();
    
            // 向list的位置0插入COUNT个数
            for (int i=0; i<COUNT; i++){
            	list.add(0, i);
            }
    
            long endTime = System.currentTimeMillis();
            long interval = endTime - startTime;
            System.out.println(name + " : 插入 "+COUNT+"元素, 使用的时间是 " + interval+" ms");
        }
    
        /**
         * 指定的List 的子类中删除元素,并统计删除的时间
         * @param list List 的子类
         * @param name 子类的名称
         */
        private static void deleteData(List<Object> list,String name) {
            long startTime = System.currentTimeMillis();
    
            // 删除list第一个位置元素
            for (int i=0; i<COUNT; i++)
                list.remove(0);
    
            long endTime = System.currentTimeMillis();
            long interval = endTime - startTime;
            System.out.println(name + " : 删除 "+COUNT+"元素, 使用的时间是 " + interval+" ms");
        }
    
        /**
         * 指定的List 的子类中读取元素,并统计读取的时间
         * @param list List 的子类
         * @param name 子类的名称
         */
        private static void readAccessData(List<Object> list,String name) {
            long startTime = System.currentTimeMillis();
    
            // 读取list元素
            for (int i = 0; i < COUNT; i++)
                list.get(i);
    
            long endTime = System.currentTimeMillis();
            long interval = endTime - startTime;
            System.out.println(name + " : 随机读取 "+COUNT+"元素, 使用的时间是 " + interval+" ms");
        }
    }
    
    

    运行结果:

    ....开始测试插入元素..........
    ArrayList : 插入 100000元素, 使用的时间是 970 ms
    LinkedList : 插入 100000元素, 使用的时间是 17 ms
    Vector : 插入 100000元素, 使用的时间是 968 ms
    Stack : 插入 100000元素, 使用的时间是 888 ms
    ....开始测试读取元素..........
    ArrayList : 随机读取 100000元素, 使用的时间是 6 ms
    LinkedList : 随机读取 100000元素, 使用的时间是 10255 ms
    Vector : 随机读取 100000元素, 使用的时间是 8 ms
    Stack : 随机读取 100000元素, 使用的时间是 4 ms
    ....开始测试删除元素..........
    ArrayList : 删除 100000元素, 使用的时间是 1460 ms
    LinkedList : 删除 100000元素, 使用的时间是 9 ms
    Vector : 删除 100000元素, 使用的时间是 1472 ms
    Stack : 删除 100000元素, 使用的时间是 894 ms
    
    

    这里写图片描述

    4.分析ArrayList和LinkedList运行结果

    从运行的结果可以看出,ArrayList和LinkedLis适用各自的场景中!
    为什么ArrayList读取速度快于LinkedList,而插入和删除速度又慢于LinkedList?
    前面章节分析了这两个类的源码!

    (1)ArrayList随机读取的时候采用的是get(index),根据指定位置读取元素,而LinkedList则采用size/2 ,二分法去加速一次读取元素!
    源代码如下:
    ArrayList:

     public E get(int index) {
            rangeCheck(index);
    
            return elementData(index);
     }
     E elementData(int index) {
            return (E) elementData[index];//直接通过数组的下标来读取元素
        }
    

    LinkedList:

    Node<E> node(int index) {
            // assert isElementIndex(index);
    
            if (index < (size >> 1)) {
                Node<E> x = first;
                for (int i = 0; i < index; i++)
                    x = x.next;
                return x;
            } else {
                Node<E> x = last;
                for (int i = size - 1; i > index; i--)
                    x = x.prev;
                return x;
            }
        }
    
    

    (2)ArrayList插入时候要判断容量,删除时候要将数组移位,有一个复制操作!而LinkedList直接插入,不用判断容量,删除的时候也是直接删除跳转指针节点,没有复制的操作!
    源代码如下:
    ArrayList:

    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // 判断是否要增容
            elementData[size++] = e;
            return true;
        }
    

    LinkedList:

    public boolean add(E e) {
            linkLast(e);
            return true;
        }
        
      void linkLast(E e) {
            final Node<E> l = last;
            final Node<E> newNode = new Node<>(l, e, null);
            last = newNode;
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;
        }
     
    

    欢迎访问我的csdn博客,我们一同成长!

    "不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!"

    博客首页:http://blog.csdn.net/u010648555

  • 相关阅读:
    Mysql一些复杂的语句
    Tomcat部署记事
    [转]Java中的事务
    Junit单元测试笔记
    Mysql之执行计划
    当产品部署出现问题时
    CSS之绝对定位那些事
    CSS之浮动那些事
    Tomcat一些小事
    NEC的学习笔记
  • 原文地址:https://www.cnblogs.com/aflyun/p/6492791.html
Copyright © 2020-2023  润新知