zoukankan      html  css  js  c++  java
  • Java中arraylist和linkedlist源代码分析与性能比較


    Javaarraylistlinkedlist源代码分析与性能比較


    1,简单介绍


    java开发中比較经常使用的数据结构是arraylistlinkedlist,本文主要从源代码角度分析arraylistlinkedlist的性能。


    2arraylist源代码分析

             Arraylist底层的数据结构是一个对象数组。有一个size的成员变量标记数组中元素的个数,例如以下图:

         * The array buffer into which the elements of the ArrayList are stored.
         * The capacity of the ArrayList is the length of this array buffer.
         */
        private transient Object[] elementData;
    
        /**
         * The size of the ArrayList (the number of elements it contains).
         *
         * @serial
         */
        private int size;


            在构造函数中Arraylist初始化为一个长度为10的对象数组。例如以下:    

        /**
         * Constructs an empty list with the specified initial capacity.
         *
         * @param  initialCapacity  the initial capacity of the list
         * @throws IllegalArgumentException if the specified initial capacity
         *         is negative
         */
        public ArrayList(int initialCapacity) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            this.elementData = new Object[initialCapacity];
        }
    
    
        /**
         * Constructs an empty list with an initial capacity of ten.
         */
        public ArrayList() {
            this(10);
        }

            Arraylist在添加数据时,首先推断数组是否超过原始分配数组的长度。假设超过。则通过数组复制的形式扩大数组然后再添加数组元素。时间复杂度处于O(1)O(n)之间。源代码例如以下:

        /**
         * Appends the specified element to the end of this list.
         *
         * @param e element to be appended to this list
         * @return <tt>true</tt> (as specified by {@link Collection#add})
         */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    


        private void ensureCapacityInternal(int minCapacity) {
            modCount++;
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }

       /**
         * Increases the capacity to ensure that it can hold at least the
         * number of elements specified by the minimum capacity argument.
         *
         * @param minCapacity the desired minimum capacity
         */
        private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    


         Arraylist在删除数据时,首先会推断数组是否越界,然后会做一个数组从后向前复制的操作,时间复杂度是O(N),源代码例如以下图:

        /**
         * Removes the element at the specified position in this list.
         * Shifts any subsequent elements to the left (subtracts one from their
         * indices).
         *
         * @param index the index of the element to be removed
         * @return the element that was removed from the list
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E remove(int index) {
            rangeCheck(index);
    
            modCount++;
            E oldValue = elementData(index);
    
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            elementData[--size] = null; // Let gc do its work
    
            return oldValue;
        }

    Arraylist在改动数据时,首先推断第i个元素是否越界,然后直接做赋值操作。时间复杂度是O(1)


        /**
         * Replaces the element at the specified position in this list with
         * the specified element.
         *
         * @param index index of the element to replace
         * @param element element to be stored at the specified position
         * @return the element previously at the specified position
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E set(int index, E element) {
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }

    Arraylist在获取数据时,首先判读第i个元素是否越界,然后获取对象数组中的第i个元素时间复杂度是O(1)。源代码例如以下图:

        /**
         * Returns the element at the specified position in this list.
         *
         * @param  index index of the element to return
         * @return the element at the specified position in this list
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E get(int index) {
            rangeCheck(index);
    
            return elementData(index);
        }


    3linkedlist源代码分析


                    Linkedlist的用到的底层数据结构是双向链表,数据结构例如以下图:

        private static class Node<E> {
            E item;
            Node<E> next;
            Node<E> prev;
    
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        }

    Linkedlist的成员变量主要有三个,size表示链表的长度,first指向链表的头部,last指向链表的尾部,源代码例如以下图:

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
        transient int size = 0;
    
        /**
         * Pointer to first node.
         * Invariant: (first == null && last == null) ||
         *            (first.prev == null && first.item != null)
         */
        transient Node<E> first;
    
        /**
         * Pointer to last node.
         * Invariant: (first == null && last == null) ||
         *            (last.next == null && last.item != null)
         */
        transient Node<E> last;
    

    Linkedlist的添加操作。仅仅是在链表的尾部添加一个节点,时间复杂度是O(1)。源代码例如以下图:

        /**
         * Appends the specified element to the end of this list.
         *
         * <p>This method is equivalent to {@link #addLast}.
         *
         * @param e element to be appended to this list
         * @return {@code true} (as specified by {@link Collection#add})
         */
        public boolean add(E e) {
            linkLast(e);
            return true;
        }


        /**
         * Links e as last element.
         */
        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++;
        }


    Linkedlist的删除操作。首先推断删除的位置是否越界。然后找到第i个元素,最后删除第一个元素,由于在删除的时候要依据元素的位置获取元素,所以时间复杂度是O(N)。源代码例如以下:

        /**
         * Removes the element at the specified position in this list.  Shifts any
         * subsequent elements to the left (subtracts one from their indices).
         * Returns the element that was removed from the list.
         *
         * @param index the index of the element to be removed
         * @return the element previously at the specified position
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E remove(int index) {
            checkElementIndex(index);
            return unlink(node(index));
        }
    </pre><pre code_snippet_id="1635127" snippet_file_name="blog_20160405_24_2093084" name="code" class="java">    /**
         * Returns the (non-null) Node at the specified element 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;
            }
        }


        /**
         * Unlinks non-null node x.
         */
        E unlink(Node<E> x) {
            // assert x != null;
            final E element = x.item;
            final Node<E> next = x.next;
            final Node<E> prev = x.prev;
    
            if (prev == null) {
                first = next;
            } else {
                prev.next = next;
                x.prev = null;
            }
    
            if (next == null) {
                last = prev;
            } else {
                next.prev = prev;
                x.next = null;
            }
    
            x.item = null;
            size--;
            modCount++;
            return element;
        }

            Linkedlist的改动操作。首先是推断数组是否越界。然后获取当前位置的元素。最后做改动操作,因为在获取当前位置的元素时,须要遍历链表。所以时间复杂度是O(N),源代码例如以下:

     

        /**

         * Replaces the element at the specified position in this list with the
         * specified element.
         *
         * @param index index of the element to replace
         * @param element element to be stored at the specified position
         * @return the element previously at the specified position
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E set(int index, E element) {
            checkElementIndex(index);
            Node<E> x = node(index);
            E oldVal = x.item;
            x.item = element;
            return oldVal;
        }

        /**
         * Returns the (non-null) Node at the specified element 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;
            }
        }

            Linkedlist的获取元素操作。首先是推断数组是否越界,然后获取当前位置的元素,因为在获取当前位置的元素时,须要遍历链表,所以时间复杂度是O(N),源代码例如以下:

        /**
         * Returns the element at the specified position in this list.
         *
         * @param index index of the element to return
         * @return the element at the specified position in this list
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E get(int index) {
            checkElementIndex(index);
            return node(index).item;
        }

        /**
         * Returns the (non-null) Node at the specified element 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;
            }
        }


    4arraylistlinkedlist的效率分析


     

    Add()

    Remove(int i)

    Set(int i, E e)

    Get(int i)

    Arraylist

    O(1)-O(N)

    O(N)

    O(1)

    O(1)

    Linkedlist

    O(1)

    O(N)

    O(N)

    O(N)


     


    
  • 相关阅读:
    12.10
    4.06Android使用EditText小技巧汇总
    4.05
    4.04Android学习
    4.03Android学习
    4.02Android学习
    4.01Android学习
    3.31构建之法读后感3
    3.30Android学习
    3.29Android学习
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7301287.html
Copyright © 2011-2022 走看看