JAVA集合二 ——list(04 LinkedList)


JAVA集合二 ——list(04 LinkedList)
     *特別聲明:

     *本文只是備忘錄。
     

    

     JAVA中List的實現主要有ArrayList、vector、stack、LinkedList,以及一個抽象的類AbstractList.

1、LinkedLIst

     LinkedList 被稱作雙向鏈表。索引速度慢,插入、刪除速度快。

     爲什麼被成爲雙向鏈表,應爲當前對象擁有了該對象之前的對象的引用和該對象之後的引用。

     不同於ArrayList通過數組保存對象,LinkedList通過一個內部數據結構Node<E>來保存對象。

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

我們可以看到 該數據結構中保存了3個對象,一個是當前的對象 Item,一個上一個對象的引用prev,一個後一個對象的引用next。

 每次插入元素的時候只需要保存前後元素即可。但是如果索引就需要遍歷整個linkedLis(當然其實是一半)。

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;

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

LinkedList保存了對象個數,第一個和最後一個對象。方便用來計算。

來看看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++;
}

add方法在末尾添加一個對象,只需要將原來的末尾對象oldLast取出,然後將oldLast的next指向新加入的對象。同時將該對象的prev指向oldLast即可。當然新加如的對象就是最後位置的對象(當然需要創建一個Node結構),需要賦值給last(上面說的LinkedList保存的最後對象)。

另外一個在指定位置加入對象的方法:

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

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
  }
  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++;
   }


通過linkBefore來插入對象,linkBefore()方法2個參數,一個是插入的對象,一個是插入對象原先位置的node信息。

關鍵的方法是node(index)方法,查找指定位置的Node對象的方法。來看看如何實現:

 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。根據傳入的index的值判斷是衝前獲取,還是衝後獲取,減少循環次數。

涉及到linkedList的索引操作都需要遍歷整個list,所以會比較慢。

發佈了13 篇原創文章 · 獲贊 10 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章