集合(二)走進LinkedList的內心

集合(一)扒掉ArrayList的外衣

集合(二)走進LinkedList的內心

集合(三)HashMap背後的故事

LinkedList是什麼?

* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces.  Implements all optional list operations, and permits all
* elements (including {@code null}).

 LinkedList是實現List和Deque的雙向鏈表,可以作爲隊列或者雙端隊列,非線程安全。

/**
 * Constructs an empty list.
 */
public LinkedList() {
}

/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param  c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

LinkedList可以直接將一個ArrayList添加到一個隊列裏面。

LinkedList的變量屬性很簡單size(集合長度)、first(頭節點),last(尾節點)。其添加方法除了add()、addAll()還有addFirst(),addLast()。

我們重點看一下addAll的源碼操作:

public boolean addAll(int index, Collection<? extends E> c) {
    //檢查添加位置是否越界,只能在[0,size]區間添加
    checkPositionIndex(index);
    //添加的Collection轉爲數組
    Object[] a = c.toArray();
    int numNew = a.length;
    if (numNew == 0)
        return false;

    Node<E> pred, succ;
    if (index == size) {
        //從集合最後插入數據
        succ = null;
        pred = last;
    } else {
        //從集合中間插入數據  找到index位置的當前對象
        succ = node(index);
        pred = succ.prev;
    }
    //遍歷數組按隊列形式插入集合
    for (Object o : a) {
        @SuppressWarnings("unchecked") E e = (E) o;
        Node<E> newNode = new Node<>(pred, e, null);
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        pred = newNode;
    }

    if (succ == null) {
        last = pred;
    } else {
        pred.next = succ;
        succ.prev = pred;
    }
    //集合當前長度
    size += numNew;
    //操作次數+1
    modCount++;
    return true;
}

remove數據主要操作步驟查詢到要刪除的數據,將該數據的前一個對象和後一個對象綁在一起:

/**
 * 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) {
    //檢查移除數據的索引是否在[0,size)區間內
    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;
}

LinkedList的插入刪除操作大同小異:先找到、再關聯前後對象。

在內存中,鏈表不是按順序存放的,而是通過指針連在一起,爲了訪問某一元素,必須從鏈頭開始順着指針才能找到某一個元素。

與ArrayList比較:

  1. 數據結構不同,ArrayList是數組結構,LinkedList是鏈表結構;
  2. ArrayList查詢數據比LinkedList快,在內存中數組爲連續的內存塊,而鏈表是靠指針連接的,後者在查詢時需要移動指針從一端到另一端[0,size>>1)或者[size>>1,size)去查詢;
  3. 添加和刪除數據時,ArrayList需要移動數據,LinkedList效率高
  4. 兩者都是非線程安全的,Vector是線程安全的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章