ArrayList和LinkedList部分源码分析性能差异

ArrayList底层为数组结构,add方法:

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);//这是一个本地native方法
        elementData[index] = element;
        size++;
    }

set方法:

public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

LinkedList底层为链表结构,set方法:

    public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }

看一下Node:

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

看一下node(index)方法是如何根据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的add方法:

 public void add(int index, E element) {
        checkPositionIndex(index);//检查下标合法

        if (index == size)
            linkLast(element);//在末尾加元素
        else
            linkBefore(element, node(index));//在中间加元素
    }
void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);//构造新的最后Node节点,设置后一个元素为null
        last = newNode;
        if (l == null)//数组内没有元素
            first = newNode;
        else//设置前一个元素的后指向
            l.next = newNode;
        size++;
        modCount++;
    }
linkLast方法比较简单,看一下linkBefore:
 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);//构造新的Node节点,设置前后指向
        succ.prev = newNode;//设置后一个元素的前指向
        if (pred == null)//设置前一个元素的后指向
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

因此:

ArrayList在随机访问(get,set)方面更高效(直接根据下标就可找到元素,LinkedList需要从最前或者最后进行依次查找)

LinkedList在List的中间插入和移除时更高效(LinkedList最多涉及三个元素的的更改,ArrayList需要对中间插入元素后面的所有元素进行后移一位的操作)

另外:

 

posted on 2017-03-02 11:06  伪善者ql  阅读(166)  评论(0编辑  收藏  举报

导航