• Java 集合系列06 List总结


    1. List概括

      

     (1)List是一个接口,它继承Collection接口,代表有序的队列。

     (2)ArrayList,LinkedList,Vector都是List的实现类。

      ArrayList是一个数组队列,相当于动态数组,是由数组实现的,随机访问效率高,随机插入,增删效率低。

      LinkedList是一个双向链表,随机插入,增删效率高,但是随机访问效率低。

      Vector和ArrayList一样,都是采用了数组的数据结构,但是ArrayList是非线程安全的,而Vector是线程安全的。

    2. List的使用场景

      (1)对于需要快速插入,删除元素,应该选择LinkedList;

      (2)对于需要快速随机访问元素,应该选择ArrayList;

      (3)Vector是线程安全的,效率较低,现在使用较少;

      几种遍历实现:

    public class CollectionCompare {
    
        public static final int COUNT = 1000;
        private static ArrayList arrayList = new ArrayList();
        private static LinkedList linkedList = new LinkedList();
        private static Vector vector = new Vector();
    
        public static void main(String[] args) {
    
            insertByPosition(arrayList);
            insertByPosition(linkedList);
            insertByPosition(vector);
    
            getByPosition(arrayList);
            getByPosition(linkedList);
            getByPosition(vector);
    
            removeByPosition(arrayList);
            removeByPosition(linkedList);
            removeByPosition(vector);
    
        }
      //获取
    private static void getByPosition(List list) { long startTime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { list.get(i); } long endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println(getListName(list) + ":get " + COUNT + " elements use time " + interval + "ms"); }
      //插入
    public static void insertByPosition(List list){ long startTime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { list.add(0,i); } long endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println(getListName(list) + ":insert " + COUNT + " elements use time " + interval + "ms"); }   
      //删除
    public static void removeByPosition(List list){ long startTime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { list.remove(0); } long endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println(getListName(list) + ":remove " + COUNT + " elements use time " + interval + "ms"); } private static String getListName(List list) { if (list instanceof ArrayList){ return "ArrayList"; }else if(list instanceof LinkedList){ return "LinkedList"; }else if(list instanceof Vector){ return "Vector"; }else{ return "List"; } } }

    3. LinkedList和ArrayList性能差异分析

      LinkedList中指定位置插入元素

        //在指定位置插入元素
        public void add(int index, E element) {
            checkPositionIndex(index);
    
            if (index == size)
                linkLast(element);
            else
                linkBefore(element, node(index));
        }
    
        //先要找到要插入位置的节点,如果要插入位置小于集合一半大小,则从前开始查找,否则从后开始找
        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;
            }
        }
    
        //新建节点Node,插入元素
        void linkBefore(E e, Node<E> succ) {
            // assert succ != null;
            final Node<E> pred = succ.prev;
            final Node<E> newNode = new Node<>(pred, e, succ);
            succ.prev = newNode;
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            size++;
            modCount++;
        }    

      给LinkedList指定位置插入元素,调用add(int index, E element)方法,需要先找到插入节点的位置index;而插入位置时:如果index<size/2,则从前往后开始找,否则从后往前开始找,找到index位置后,然后再插入新节点。

      ArrayList中指定位置插入元素

        public void add(int index, E element) {
            rangeCheckForAdd(index);
            modCount++;
            final int s;
            Object[] elementData;
            if ((s = size) == (elementData = this.elementData).length)
                elementData = grow();
            System.arraycopy(elementData, index,
                             elementData, index + 1,
                             s - index);
            elementData[index] = element;
            size = s + 1;
        }

      ArrayList中插入元素主要耗时的是调用System.arraycopy(elementData, index, elementData, index + 1, size - index)方法,这是一个native方法,底层是c/c++实现,在插入过程中会移动index位置后的所有元素。

      所以使用ArrayList插入元素相较于LinkedList耗时。

      随机访问LinkedList元素

        //获取指定位置的元素
        public E get(int index) {
            checkElementIndex(index);
            return node(index).item;
        }
    
        //获取指定位置的节点,和插入元素原理相同
        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;
            }
        }

      随机访问LinkedList和插入元素的原理相同,也是先找到指定位置的节点,然后再返回元素。

      随机访问ArrayList中的元素

        public E get(int index) {
            Objects.checkIndex(index, size);
            return elementData(index);
        }

      随机访问ArrayList中元素通过调用get()方法,直接返回数组中index位置的元素,而不需要像LinkedList那样查找元素。

      所以使用ArrayList随机访问元素相较于LinkedList元素效率较高。

  • 相关阅读:
    angular读书笔记(三)
    angular读书笔记(二)
    angularjs读书笔记(一)
    angular和web前端的一些细节
    angular的service
    angular学习之directive
    最近学的twig
    最近学的grunt
    今天学的angularJS
    android即时通讯开发笔记(一)绪论~实现用户登录,自动登录,注销功能
  • 原文地址:https://www.cnblogs.com/homle/p/14952761.html
Copyright © 2020-2023  润新知