JDK 1.7源碼閱讀筆記(三)集合類之LinkedList

前言

  (1)LinkedList的內部實現是雙向鏈表,繼承了AbstractSequentialList,實現了List, Deque, Cloneable, java.io.Serializable接口,因此LinkdeList本身支持就支持雙端隊列操作。LinkedList**允許所有元素(包括 null)**。除了實現 List 接口外,LinkedList 類還爲在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方法。這些操作允許將鏈接列表用作堆棧、隊列或雙端隊列。

  此類實現 Deque 接口,爲 add、poll 提供先進先出隊列操作,以及其他堆棧和雙端隊列操作。
  LinkedList與ArrayList一樣實現List接口,只是ArrayList是List接口的大小可變數組的實現,LinkedList是List接口鏈表的實現。基於鏈表實現的方式使得LinkedList在插入和刪除時更優於ArrayList,而隨機訪問則比ArrayList遜色些。

  (2)此實現不是同步的。如果多個線程同時訪問一個鏈接列表,而其中至少一個線程從結構上修改了該列表,則它必須 保持外部同步。(結構修改指添加或刪除一個或多個元素的任何操作;僅設置元素的值不是結構修改。)這一般通過對自然封裝該列表的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用 Collections.synchronizedList 方法來“包裝”該列表。最好在創建時完成這一操作,以防止對列表進行意外的不同步訪問,如下所示:

     List list = Collections.synchronizedList(new LinkedList(...));

  (3) 此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗 的:在迭代器創建之後,如果從結構上對列表進行修改,除非通過迭代器自身的 remove 或 add 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不冒將來不確定的時間任意發生不確定行爲的風險。

  注意,迭代器的快速失敗行爲不能得到保證,一般來說,存在不同步的併發修改時,不可能作出任何硬性保證。快速失敗迭代器盡最大努力拋出 ConcurrentModificationException。因此,編寫依賴於此異常的程序的方式是錯誤的,正確做法是:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。

  (4)和ArrayList類似,在類內部同樣出現了transient關鍵字,這在ArrayList中已經解釋過了,在這裏不做過多的解釋了。

        transient int size = 0;
        transient Node<E> first;
        transient Node<E> last;

源碼

1>LinkedList內部通過Node來抽象一個節點,結點包括值和前向指針和後向指針。Node的定義是在LinkedList內部,作爲靜態內部類存在。

private static class Node<E> {  
        E item;//結點的值  
        Node<E> next;//結點的後向指針  
        Node<E> prev;//結點的前向指針   
        //構造函數中已完成Node成員的賦值 
        Node(Node<E> prev, E element, Node<E> next) {  
            this.item = element;//結點的值賦值爲element  
            this.next = next;//後向指針賦值  
            this.prev = prev;//前向指針賦值  
        }  
}

2>LinkedList 的關鍵源碼

//LinedList繼承了AbstractSequentialList,支持泛型
public class LinkedList<E>  
    extends AbstractSequentialList<E>  
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable  
{  
    transient int size = 0;//鏈表元素個數  
    transient Node<E> first;//鏈表頭結點 
    transient Node<E> last;//鏈表尾結點  

    //生成一個空的鏈表  
    public LinkedList() {  
    }  

    //按c裏面的元素生成一個LinkedList  
    public LinkedList(Collection<? extends E> c) {  
        this();//調用空的構造函數  
        addAll(c);//將c裏面的元素添加到空鏈表尾部  
    }  
    //首部增加結點,結點的值爲e  
    private void linkFirst(E e) {  
        final Node<E> f = first;//f指向頭結點  
        //生成一個新結點,結點的值爲e,其前向指針爲null,後向指針爲f  
        final Node<E> newNode = new Node<>(null, e, f);
        //first指向新生成的結點,f保存着老的頭結點信息  
        first = newNode;
        if (f == null)  
            //如果f爲null,則表示整個鏈表目前是空的,則尾結點也指向新結點
            last = newNode;  
        else  
            //f(老的頭結點)的前向指針指向最新的結點信息  
            f.prev = newNode;
        size++;//元素個數+1.  
        modCount++;//修改次數+1  
    }  
    //尾部增加結點,結點的值爲e  
    void linkLast(E e) {  
        final Node<E> l = last;//l指向尾結點  
        //生成一個新結點,結點的值爲e,其前向指針爲l,後向指針爲null  
        final Node<E> newNode = new Node<>(l, e, null);
        //last指向新生成的結點,l保存着老的尾結點信息  
        last = newNode;
        if (l == null)  
            //如果l爲null,則表示整個鏈表目前是空的,則頭結點也指向新結點
            first = newNode;  
        else  
            //l(老的尾結點)的後向指針指向最新的結點信息
            l.next = newNode;  
        size++;//元素個數+1  
        modCount++;//修改次數+1  
    }  
    //非空結點succ之前插入新結點,新結點的值爲e  
    void linkBefore(E e, Node<E> succ) {  
        // assert succ != null;//外界調用需保證succ不爲null,否則程序會拋出空指針異常  
        final Node<E> pred = succ.prev;//pred指向succ的前向結點  
        //生成一個新結點,結點的值爲e,其前向指針指向pred,後向指針指向succ  
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;//succ的前向指針指向newNode  
        if (pred == null)  
            //如果pred爲null,則表示succ爲頭結點,此時頭結點指向最新生成的結點newNode  
            first = newNode;
        else  
            //pred的後向指針指向新生成的結點,此時已經完成了結點的插入操作
            pred.next = newNode;  
        size++;//元素個數+1  
        modCount++;//修改次數+1  
    }  

    //刪除頭結點,並返回該結點的值  
    private E unlinkFirst(Node<E> f) {  
        // assert f == first && f != null;//需確保f爲頭結點,且鏈表不爲Null  
        final E element = f.item;//獲得結點的值  
        final Node<E> next = f.next;//next指向f的後向結點  
        f.item = null;//釋放數據結點  
        f.next = null;//釋放f的後向指針  
        first = next;//first指向f的後向結點  
        if (next == null)  
            //如果next爲null,則表示f爲last結點,此時鏈表即爲空鏈表 
            last = null; 
        else  
            //修改next的前向指針,因爲first結點的前向指針爲null 
            next.prev = null; 
        size--;//元素個數-1  
        modCount++;//修改次數+1  
        return element;  
    }  
    //刪除尾結點,並返回尾結點的內容  
    private E unlinkLast(Node<E> l) {  
        // assert l == last && l != null;//需確保l爲尾結點,且鏈表不爲null  
        final E element = l.item;//獲得結點的值  
        final Node<E> prev = l.prev;//prev執行l的前向結點  
        l.item = null;//釋放l結點的值  
        l.prev = null; //釋放l結點的前向指針  
        last = prev;//last結點指向l的前向結點  
        if (prev == null) 
            //如果prev爲null,則表示l爲first結點,此時鏈表即爲空鏈表  
            first = null; 
        else  
            //修改prev的後向指針,因爲last結點的後向指針爲null 
            prev.next = null; 
        size--;//元素個數-1  
        modCount++;//修改次數+1  
        return element;  
    }  
    //刪除結點x  
    E unlink(Node<E> x) {  
        // assert x != null;//需確保x不爲null,否則後續操作會拋出空指針異常  
        final E element = x.item;//保存x結點的值  
        final Node<E> next = x.next;//next指向x的後向結點  
        final Node<E> prev = x.prev;//prev指向x的前向結點  

        if (prev == null) {  
            //如果prev爲空,則x結點爲first結點,此時first結點指向next結點(x的後向結點)  
            first = next;
        } else {  
            prev.next = next;//x的前向結點的後向指針指向x的後向結點  
            x.prev = null;//釋放x的前向指針  
        }  

        if (next == null) {  
            //如果next結點爲空,則x結點爲尾部結點,此時last結點指向prev結點(x的前向結點)  
            last = prev;
        } else {  
            next.prev = prev;//x的後向結點的前向指針指向x的前向結點  
            x.next = null;//釋放x的後向指針  
        }  

        x.item = null;//釋放x的值節點,此時x節點可以完全被GC回收  
        size--;//元素個數-1  
        modCount++;//修改次數+1  
        return element;  
    }  

    //獲得頭結點的值  
    public E getFirst() {  
        final Node<E> f = first;//f指向first結點  
        if (f == null)//此時鏈表爲空  
            throw new NoSuchElementException();  
        return f.item;//返回first結點的值  
    }  

    //獲得尾結點的值  
    public E getLast() {  
        final Node<E> l = last;//l指向last結點  
        if (l == null)//此時鏈表爲空  
            throw new NoSuchElementException();  
        return l.item;//返回last結點的值  
    }  

    //移除頭結點  
    public E removeFirst() {  
        final Node<E> f = first;//獲得頭結點  
        if (f == null)//此時鏈表爲空  
            throw new NoSuchElementException();  
        return unlinkFirst(f);//摘除頭結點  
    }  

    //移除尾結點  
    public E removeLast() {  
        final Node<E> l = last;//獲得尾結點  
        if (l == null)//此時鏈表爲空  
            throw new NoSuchElementException();  
        return unlinkLast(l);//摘除尾結點  
    }  

    //添加到頭結點,結點的值爲e  
    public void addFirst(E e) {  
        linkFirst(e);//添加到頭部  
    }  
    //添加到尾結點,結點值爲e  
    public void addLast(E e) {  
        linkLast(e);//添加到尾部  
    }  

    //判斷元素(值爲o)是o否在鏈表中  
    public boolean contains(Object o) {  
        return indexOf(o) != -1;//定位元素  
    }  
    //返回元素個數  
    public int size() {  
        return size;  
    }  

    //添加元素,元素值爲e  
    public boolean add(E e) {  
        linkLast(e);//添加到鏈表尾部  
        return true;
    }  
    //移除值爲o的元素,o可以爲null,找到一個刪除即返回  
    public boolean remove(Object o) {  
        if (o == null) {//元素爲null  
            for (Node<E> x = first; x != null; x = x.next) {//從頭結點開始遍歷  
                if (x.item == null) {//找到一個結點  
                    unlink(x);//刪除元素  
                    return true;  
                }  
            }  
        } else {//元素不爲空  
            for (Node<E> x = first; x != null; x = x.next) {  
                if (o.equals(x.item)) {  
                    unlink(x);  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  
    //將c中的元素都添加到當前鏈表中  
    public boolean addAll(Collection<? extends E> c) {  
        return addAll(size, c);//添加到鏈表尾部  
    }  
    //第序號爲index處,添加c中所有的元素到當前鏈表中(後向添加的)  
    public boolean addAll(int index, Collection<? extends E> c) {  
        checkPositionIndex(index);//判斷index是否超出界  

        Object[] a = c.toArray();//將集合轉換爲數組  
        int numNew = a.length;  
        if (numNew == 0)  
            return false;  

        Node<E> pred, succ;  
        if (index == size) {//如果index爲元素個數,即第index個結點爲尾結點  
            succ = null;  
            pred = last;//指向爲結點  
        } else {  
            succ = node(index);//succ指向第index個結點  
            pred = succ.prev;//pred指向succ的前向結點  
        }  
        //for循環結束後,a裏面的元素都添加到當前鏈表裏面了,後向添加  
        for (Object o : a) {  
            @SuppressWarnings("unchecked") E e = (E) o;  
            //新生成一個結點,結點的前向指針指向pred,後向指針爲null  
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)  
                first = newNode;//如果pred爲null,則succ爲當前頭結點,  
            else  
                pred.next = newNode;//pred的後向指針指向新結點  
            pred = newNode;//pred移動到新結點  
        }  

        if (succ == null) {  
            last = pred;//succ爲null,這表示index爲尾結點之後  
        } else {  
            //pred表示所有元素添加之後的最後結點,此時pred的後向指針指向之前的記錄的結點  
            pred.next = succ;
            succ.prev = pred;//之前記錄的結點指向添加元素之後的最後結點  
        }  

        size += numNew;//元素個數+num  
        modCount++;//修改次數+1  
        return true;  
    }  
    //清除鏈表裏面的所有元素  
    public void clear() {  
        for (Node<E> x = first; x != null; ) {  
            Node<E> next = x.next;  
            x.item = null;//釋放值結點,便於GC回收  
            x.next = null;//釋放前向指針  
            x.prev = null;//釋放後向指針  
            x = next;//後向遍歷  
        }  
        first = last = null;//釋放頭尾結點  
        size = 0;  
        modCount++;  
    }  
    //獲得第index個結點的值  
    public E get(int index) {  
        checkElementIndex(index);  
        return node(index).item;//點位第index結點,返回值信息  
    }  
    //設置第index元素的值  
    public E set(int index, E element) {  
        checkElementIndex(index);  
        Node<E> x = node(index);//定位第index個結點  
        E oldVal = x.item;  
        x.item = element;  
        return oldVal;  
    }  

    //第index個結點之前添加結點  
    public void add(int index, E element) {  
        checkPositionIndex(index);  

        if (index == size)  
            linkLast(element);  
        else  
            linkBefore(element, node(index));  
    }  
    //刪除第index個結點  
    public E remove(int index) {  
        checkElementIndex(index);  
        return unlink(node(index));  
    }  
    //判斷index是否是鏈表中的元素的下標  
    private boolean isElementIndex(int index) {  
        return index >= 0 && index < size;  
    }  
    //判斷index是否是鏈表中的元素的下標  
    private boolean isPositionIndex(int index) {  
        return index >= 0 && index <= size;  
    }  

    private String outOfBoundsMsg(int index) {  
        return "Index: "+index+", Size: "+size;  
    }  

    private void checkElementIndex(int index) {  
        if (!isElementIndex(index))  
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
    }  

    private void checkPositionIndex(int index) {  
        if (!isPositionIndex(index))  
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
    }  

    //定位鏈表中的第index個結點  
    Node<E> node(int index) {  
        // assert isElementIndex(index);//確保是合法的下標,即0<=index<=size  
        //index小於size的一半時,從頭向後找  
        if (index < (size >> 1)) {  
            Node<E> x = first;  
            for (int i = 0; i < index; i++)  
                x = x.next;  
            return x;  
        } else {//index大於size的一半時,從尾向前找  
            Node<E> x = last;  
            for (int i = size - 1; i > index; i--)  
                x = x.prev;  
            return x;  
        }  
    }  

    //定位元素,首次出現的元素的值爲o的結點序號  
    public int indexOf(Object o) {  
        int index = 0;  
        if (o == null) {  
            for (Node<E> x = first; x != null; x = x.next) {  
                if (x.item == null)  
                    return index;  
                index++;  
            }  
        } else {  
            for (Node<E> x = first; x != null; x = x.next) {  
                if (o.equals(x.item))  
                    return index;  
                index++;  
            }  
        }  
        return -1;  
    }  

    //定位元素,最後一次出現的元素值爲o的元素序號  
    public int lastIndexOf(Object o) {  
        int index = size;  
        if (o == null) {  
            for (Node<E> x = last; x != null; x = x.prev) {  
                index--;  
                if (x.item == null)  
                    return index;  
            }  
        } else {  
            for (Node<E> x = last; x != null; x = x.prev) {  
                index--;  
                if (o.equals(x.item))  
                    return index;  
            }  
        }  
        return -1;  
    }  

    //實現隊列操作,返回第一個元素的值  
    public E peek() {  
        final Node<E> f = first;  
        return (f == null) ? null : f.item;  
    }  

    //實現隊列操作,返回第一個結點  
    public E element() {  
        return getFirst();  
    }  
    //實現隊列操作,彈出第一個結點  
    public E poll() {  
        final Node<E> f = first;  
        return (f == null) ? null : unlinkFirst(f);  
    }  
    //刪除結點  
    public E remove() {  
        return removeFirst();  
    }  
    //添加結點  
    public boolean offer(E e) {  
        return add(e);  
    }  
    //添加頭結點  
    public boolean offerFirst(E e) {  
        addFirst(e);  
        return true;  
    }  
    //添加尾結點  
    public boolean offerLast(E e) {  
        addLast(e);  
        return true;  
    }  

    //返回頭結點的值  
    public E peekFirst() {  
        final Node<E> f = first;  
        return (f == null) ? null : f.item;  
     }  

    //返回尾結點的值  
    public E peekLast() {  
        final Node<E> l = last;  
        return (l == null) ? null : l.item;  
    }  

    //彈出第一個結點  
    public E pollFirst() {  
        final Node<E> f = first;  
        return (f == null) ? null : unlinkFirst(f);  
    }  

    //彈出最後一個結點  
    public E pollLast() {  
        final Node<E> l = last;  
        return (l == null) ? null : unlinkLast(l);  
    }  

    //添加頭部結點  
    public void push(E e) {  
        addFirst(e);  
    }  

    //彈出第一個結點  
    public E pop() {  
        return removeFirst();  
    }  

    //刪除值爲o的結點  
    public boolean removeFirstOccurrence(Object o) {  
        return remove(o);  
    }  

    //刪除值爲o的結點  
    public boolean removeLastOccurrence(Object o) {  
        if (o == null) {  
            for (Node<E> x = last; x != null; x = x.prev) {  
                if (x.item == null) {  
                    unlink(x);  
                    return true;  
                }  
            }  
        } else {  
            for (Node<E> x = last; x != null; x = x.prev) {  
                if (o.equals(x.item)) {  
                    unlink(x);  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  

    //返回雙向迭代器  
    public ListIterator<E> listIterator(int index) {  
        checkPositionIndex(index);  
        return new ListItr(index);  
    }  
    //私有內部類,實現雙向迭代器  
    private class ListItr implements ListIterator<E> {  
        private Node<E> lastReturned = null;//記錄當前結點信息  
        private Node<E> next;//當前結點的後向結點  
        private int nextIndex;//當前結點的序號  
        private int expectedModCount = modCount;//修改次數  
        //初始化  
        ListItr(int index) {  
            next = (index == size) ? null : node(index);
            nextIndex = index;  
        }  
        //是否有結點  
        public boolean hasNext() {  
            return nextIndex < size;  
        }  
        //返回下一個結點  
        public E next() {  
            checkForComodification();  
            if (!hasNext())  
                throw new NoSuchElementException();  

            lastReturned = next;//記錄當前結點  
            next = next.next;//向後移動  
            nextIndex++;//結點序號+1  
            return lastReturned.item;  
        }  
        //是否有前向結點  
        public boolean hasPrevious() {  
            return nextIndex > 0;  
        }  
        //返回前向結點  
        public E previous() {  
            checkForComodification();  
            if (!hasPrevious())  
                throw new NoSuchElementException();  

            lastReturned = next = (next == null) ? last : next.prev;  
            nextIndex--;  
            return lastReturned.item;  
        }  
        //返回當前結點序號  
        public int nextIndex() {  
            return nextIndex;  
        }  
        //返回當前結點的前一個序號  
        public int previousIndex() {  
            return nextIndex - 1;  
        }  
        //刪除結點  
        public void remove() {  
            checkForComodification();  
            if (lastReturned == null)  
                throw new IllegalStateException();  

            Node<E> lastNext = lastReturned.next;  
            unlink(lastReturned);  
            if (next == lastReturned)  
                next = lastNext;  
            else  
                nextIndex--;  
            lastReturned = null;  
            expectedModCount++;  
        }  
        //設置當前結點的值  
        public void set(E e) {  
            if (lastReturned == null)  
                throw new IllegalStateException();  
            checkForComodification();  
            lastReturned.item = e;  
        }  
        //當前結點前面插入新結點信息  
        public void add(E e) {  
            checkForComodification();  
            lastReturned = null;  
            if (next == null)  
                linkLast(e);  
            else  
                linkBefore(e, next);  
            nextIndex++;  
            expectedModCount++;  
        }  
        //判斷迭代期間是否被修改  
        final void checkForComodification() {  
            if (modCount != expectedModCount)  
                throw new ConcurrentModificationException();  
        }  
    }  

    //返回前向迭代器  
    public Iterator<E> descendingIterator() {  
        return new DescendingIterator();  
    }  

    //前向迭代器  
    private class DescendingIterator implements Iterator<E> {  
        private final ListItr itr = new ListItr(size());  
        public boolean hasNext() {//判斷是否有前向結點  
            return itr.hasPrevious();  
        }  
        public E next() {//前向迭代  
            return itr.previous();  
        }  
        public void remove() {//刪除結點  
            itr.remove();  
        }  
    }  

    @SuppressWarnings("unchecked")  
    private LinkedList<E> superClone() {  
        try {  
            return (LinkedList<E>) super.clone();  
        } catch (CloneNotSupportedException e) {  
            throw new InternalError();  
        }  
    }  

    //拷貝操作,執行淺拷貝,只複製引用,而沒有複製引用指向的內存
    public Object clone() {  
        LinkedList<E> clone = superClone();  

        // Put clone into "virgin" state  
        clone.first = clone.last = null;  
        clone.size = 0;  
        clone.modCount = 0;  

        // Initialize clone with our elements  
        for (Node<E> x = first; x != null; x = x.next)  
            clone.add(x.item);  

        return clone;  
    }  

    //轉換爲數組  
    public Object[] toArray() {  
        Object[] result = new Object[size];  
        int i = 0;  
        for (Node<E> x = first; x != null; x = x.next)  
            result[i++] = x.item;  
        return result;  
    }  

    //轉換爲數組  
    @SuppressWarnings("unchecked")  
    public <T> T[] toArray(T[] a) {  
        if (a.length < size)  
            a = (T[])java.lang.reflect.Array.newInstance(  
                                a.getClass().getComponentType(), size);  
        int i = 0;  
        Object[] result = a;  
        for (Node<E> x = first; x != null; x = x.next)  
            result[i++] = x.item;  

        if (a.length > size)  
            a[size] = null;  

        return a;  
    }  

    private static final long serialVersionUID = 876323262645176354L;  

    //序列化  
    private void writeObject(java.io.ObjectOutputStream s)  
        throws java.io.IOException {  
        // Write out any hidden serialization magic  
        s.defaultWriteObject();  

        // Write out size  
        s.writeInt(size);  

        // Write out all elements in the proper order.  
        for (Node<E> x = first; x != null; x = x.next)  
            s.writeObject(x.item);  
    }  

    //反序列化  
    @SuppressWarnings("unchecked")  
    private void readObject(java.io.ObjectInputStream s)  
        throws java.io.IOException, ClassNotFoundException {  
        // Read in any hidden serialization magic  
        s.defaultReadObject();  

        // Read in size  
        int size = s.readInt();  

        // Read in all elements in the proper order.  
        for (int i = 0; i < size; i++)  
            linkLast((E)s.readObject());  
    }  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章