源码看JAVA【一】ArrayList与LinkedList在插入删除查询的区别

1、插入

1.1、ArrayList实现

   /**
     * 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;
    }

    /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

1.2、LinkedList实现

    /**
     * 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++;
    }

    /**
     * Inserts element e before non-null Node succ.
     */
    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++;
    }

    /**
     * Inserts the specified element at the specified position in this list.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

1.3、对比

ArrayList插入时,先将插入下标之后的所有元素往后复制一遍(下标+1);然后再将元素设置到指定下标。

LinkedList插入时,先根据值创建节点元素;然后修改插入位置前后节点的索引。

总结:ArrayList在插入时比LinkedList多进行了元素的复制,会消耗一定的时间,在插入元素时比LinkedList性能要低。

2、删除

2.1、ArrayList实现

    /**
     * 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; // clear to let GC do its work

        return oldValue;
    }

2.2、LinkedList实现

    /**
     * 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));
    }
    /**
     * 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;
    }

2.3、对比

ArrayList删除时,先将插入下标之后的所有元素往前复制一遍(下标-1);然后将元素置空,并减少List长度。

LinkedList删除时,将删除节点的前节点指针指向后节点,然后将元素置空,并减少List长度。

总结:ArrayList在删除时比LinkedList多进行了元素的复制,会消耗一定的时间,在删除元素时比LinkedList性能要低。

3、查询

3.1、ArrayList实现

E elementData(**int **index) { **return **(E) **elementData**[index]; }

3.2、LinkedList实现

_/** __ * 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; } }

2.3、对比

ArrayList查询定位时,直接根据数组索引获取元素。

LinkedList查询定位时,需要遍历到指定的位置获取元素。

总结:ArrayList在查询时比LinkedList少了元素遍历,比LinkedList性能要高。


   转载规则


《源码看JAVA【一】ArrayList与LinkedList在插入删除查询的区别》 Euler 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录