JDK11-LinkedList集合源碼(3)

1.介紹

  LinkedList 是線程不安全的,允許元素爲null的雙向鏈表。就是這麼簡單

 

2.LinkedList繼承結構一覽圖

  

3.類定義

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  • Cloneable實現克隆
  • Serializable序列化
  • List 定義了一些集合類的方法
  • Deque雙向隊列接口(就是兩端都可以進行增加刪除操作)

注意一點LinkedList並沒有實現RandomAccess所以隨機訪問是非常慢的。

 在說LinkedList之前,先介紹下AbstractSequentialList,Deque,Queue,其他的已經在前面文章介紹過,詳情請查看

   AbstractSequentialList

//此類提供List 接口的基本實現,以最大程度地減少實現由“順序訪問”數據存儲(例如鏈表)支持的接口所需的工作
public abstract class AbstractSequentialList<E> extends AbstractList<E> {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractSequentialList() {
    }

    /**
     * Returns the element at the specified position in this list.
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with {@code listIterator(index)}).  Then, it gets
     * the element using {@code ListIterator.next} and returns it.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
        返回此列表中指定位置的元素
     */
    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

    /**
     * Replaces the element at the specified position in this list with the
     * specified element (optional operation).
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with {@code listIterator(index)}).  Then, it gets
     * the current element using {@code ListIterator.next} and replaces it
     * with {@code ListIterator.set}.
     *
     * <p>Note that this implementation will throw an
     * {@code UnsupportedOperationException} if the list iterator does not
     * implement the {@code set} operation.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
       用指定的元素替換此列表中指定位置的元素
     */
    public E set(int index, E element) {
        try {
            ListIterator<E> e = listIterator(index);
            E oldVal = e.next();
            e.set(element);
            return oldVal;
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

    /**
     * Inserts the specified element at the specified position in this list
     * (optional operation).  Shifts the element currently at that position
     * (if any) and any subsequent elements to the right (adds one to their
     * indices).
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with {@code listIterator(index)}).  Then, it
     * inserts the specified element with {@code ListIterator.add}.
     *
     * <p>Note that this implementation will throw an
     * {@code UnsupportedOperationException} if the list iterator does not
     * implement the {@code add} operation.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
       將指定的元素插入此列表中的指定位置
     */
    public void add(int index, E element) {
        try {
            listIterator(index).add(element);
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

    /**
     * Removes the element at the specified position in this list (optional
     * operation).  Shifts any subsequent elements to the left (subtracts one
     * from their indices).  Returns the element that was removed from the
     * list.
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with {@code listIterator(index)}).  Then, it removes
     * the element with {@code ListIterator.remove}.
     *
     * <p>Note that this implementation will throw an
     * {@code UnsupportedOperationException} if the list iterator does not
     * implement the {@code remove} operation.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
       刪除此列表中指定位置的元素
     */
    public E remove(int index) {
        try {
            ListIterator<E> e = listIterator(index);
            E outCast = e.next();
            e.remove();
            return outCast;
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }


    // Bulk Operations

    /**
     * Inserts all of the elements in the specified collection into this
     * list at the specified position (optional operation).  Shifts the
     * element currently at that position (if any) and any subsequent
     * elements to the right (increases their indices).  The new elements
     * will appear in this list in the order that they are returned by the
     * specified collection's iterator.  The behavior of this operation is
     * undefined if the specified collection is modified while the
     * operation is in progress.  (Note that this will occur if the specified
     * collection is this list, and it's nonempty.)
     *
     * <p>This implementation gets an iterator over the specified collection and
     * a list iterator over this list pointing to the indexed element (with
     * {@code listIterator(index)}).  Then, it iterates over the specified
     * collection, inserting the elements obtained from the iterator into this
     * list, one at a time, using {@code ListIterator.add} followed by
     * {@code ListIterator.next} (to skip over the added element).
     *
     * <p>Note that this implementation will throw an
     * {@code UnsupportedOperationException} if the list iterator returned by
     * the {@code listIterator} method does not implement the {@code add}
     * operation.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
       將指定集合中的所有元素插入此列表中的指定位置
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        try {
            boolean modified = false;
            ListIterator<E> e1 = listIterator(index);
            for (E e : c) {
                e1.add(e);
                modified = true;
            }
            return modified;
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }


    // Iterators

    /**
     * Returns an iterator over the elements in this list (in proper
     * sequence).<p>
     *
     * This implementation merely returns a list iterator over the list.
     *
     * @return an iterator over the elements in this list (in proper sequence)
       返回此列表中元素的迭代器(按適當順序)
     */
    public Iterator<E> iterator() {
        return listIterator();
    }

    /**
     * Returns a list iterator over the elements in this list (in proper
     * sequence).
     *
     * @param  index index of first element to be returned from the list
     *         iterator (by a call to the {@code next} method)
     * @return a list iterator over the elements in this list (in proper
     *         sequence)
     * @throws IndexOutOfBoundsException {@inheritDoc}
       返回此列表中的元素的列表迭代器(按適當順序)
     */
    public abstract ListIterator<E> listIterator(int index);
}

Queue

  

public interface Queue<E> extends Collection<E> {
    /**
     * Inserts the specified element into this queue if it is possible to do so
     * immediately without violating capacity restrictions, returning
     * {@code true} upon success and throwing an {@code IllegalStateException}
     * if no space is currently available.
     *
     * @param e the element to add
     * @return {@code true} (as specified by {@link Collection#add})
     * @throws IllegalStateException if the element cannot be added at this
     *         time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this queue
     * @throws NullPointerException if the specified element is null and
     *         this queue does not permit null elements
     * @throws IllegalArgumentException if some property of this element
     *         prevents it from being added to this queue
       如果可以在不違反容量限制的情況下立即將指定的元素插入此隊列,則true在成功返回時返回指定的元素,  如果當前沒有可用空間,則拋出IllegalStateException。
     */
    boolean add(E e);

    /**
     * Inserts the specified element into this queue if it is possible to do
     * so immediately without violating capacity restrictions.
     * When using a capacity-restricted queue, this method is generally
     * preferable to {@link #add}, which can fail to insert an element only
     * by throwing an exception.
     *
     * @param e the element to add
     * @return {@code true} if the element was added to this queue, else
     *         {@code false}
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this queue
     * @throws NullPointerException if the specified element is null and
     *         this queue does not permit null elements
     * @throws IllegalArgumentException if some property of this element
     *         prevents it from being added to this queue
       如果可以在不違反容量限制的情況下立即將指定的元素插入此隊列
     */
    boolean offer(E e);

    /**
     * Retrieves and removes the head of this queue.  This method differs
     * from {@link #poll() poll()} only in that it throws an exception if
     * this queue is empty.
     *
     * @return the head of this queue
     * @throws NoSuchElementException if this queue is empty
       檢索並刪除此隊列的頭。沒有元素是拋出異常
     */
    E remove();

    /**
     * Retrieves and removes the head of this queue,
     * or returns {@code null} if this queue is empty.
     *
     * @return the head of this queue, or {@code null} if this queue is empty
        檢索並刪除此隊列的頭部,null如果此隊列爲空,則返回。
     */
    E poll();

    /**
     * Retrieves, but does not remove, the head of this queue.  This method
     * differs from {@link #peek peek} only in that it throws an exception
     * if this queue is empty.
     *
     * @return the head of this queue
     * @throws NoSuchElementException if this queue is empty
       檢索但不刪除此隊列的頭,沒有元素時,拋出異常
     */
    E element();

    /**
     * Retrieves, but does not remove, the head of this queue,
     * or returns {@code null} if this queue is empty.
     *
     * @return the head of this queue, or {@code null} if this queue is empty
       檢索但不刪除此隊列的頭部,null如果此隊列爲空,則返回
     */
    E peek();
}

隊列方法摘要

Deque

  

/**
  雙向隊列
  隊頭,隊尾,都可以插入刪除,繼承Queue
**/
public interface Deque<E> extends Queue<E> {
    /**
     * Inserts the specified element at the front of this deque if it is
     * possible to do so immediately without violating capacity restrictions,
     * throwing an {@code IllegalStateException} if no space is currently
     * available.  When using a capacity-restricted deque, it is generally
     * preferable to use method {@link #offerFirst}.
     *
     * @param e the element to add
     * @throws IllegalStateException if the element cannot be added at this
     *         time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
       插入一個元素到隊列前面
     */
    void addFirst(E e);

    /**
     * Inserts the specified element at the end of this deque if it is
     * possible to do so immediately without violating capacity restrictions,
     * throwing an {@code IllegalStateException} if no space is currently
     * available.  When using a capacity-restricted deque, it is generally
     * preferable to use method {@link #offerLast}.
     *
     * <p>This method is equivalent to {@link #add}.
     *
     * @param e the element to add
     * @throws IllegalStateException if the element cannot be added at this
     *         time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
        插入一個元素到隊列後面
     */
    void addLast(E e);

    /**
     * Inserts the specified element at the front of this deque unless it would
     * violate capacity restrictions.  When using a capacity-restricted deque,
     * this method is generally preferable to the {@link #addFirst} method,
     * which can fail to insert an element only by throwing an exception.
     *
     * @param e the element to add
     * @return {@code true} if the element was added to this deque, else
     *         {@code false}
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
      插入一個元素到隊列前面,如果違反容量限制,就拋出異常
     */
    boolean offerFirst(E e);

    /**
     * Inserts the specified element at the end of this deque unless it would
     * violate capacity restrictions.  When using a capacity-restricted deque,
     * this method is generally preferable to the {@link #addLast} method,
     * which can fail to insert an element only by throwing an exception.
     *
     * @param e the element to add
     * @return {@code true} if the element was added to this deque, else
     *         {@code false}
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
       插入一個元素到隊列後面,如果違反容量限制,就拋出異常
     */
    boolean offerLast(E e);

    /**
     * Retrieves and removes the first element of this deque.  This method
     * differs from {@link #pollFirst pollFirst} only in that it throws an
     * exception if this deque is empty.
     *
     * @return the head of this deque
     * @throws NoSuchElementException if this deque is empty
       檢索並刪除此deque的第一個元素  如果隊列是空 拋出NoSuchElementException
     */
    E removeFirst();

    /**
     * Retrieves and removes the last element of this deque.  This method
     * differs from {@link #pollLast pollLast} only in that it throws an
     * exception if this deque is empty.
     *
     * @return the tail of this deque
     * @throws NoSuchElementException if this deque is empty
       檢索並刪除此deque的最後一個元素 如果隊列是空 拋出NoSuchElementException
     */
    E removeLast();

    /**
     * Retrieves and removes the first element of this deque,
     * or returns {@code null} if this deque is empty.
     *
     * @return the head of this deque, or {@code null} if this deque is empty
       檢索並刪除此deque的第一個元素
     */
    E pollFirst();

    /**
     * Retrieves and removes the last element of this deque,
     * or returns {@code null} if this deque is empty.
     *
     * @return the tail of this deque, or {@code null} if this deque is empty
       檢索並刪除此deque的最後一個元素
     */
    E pollLast();

    /**
     * Retrieves, but does not remove, the first element of this deque.
     *
     * This method differs from {@link #peekFirst peekFirst} only in that it
     * throws an exception if this deque is empty.
     *
     * @return the head of this deque
     * @throws NoSuchElementException if this deque is empty
       檢索並獲得此deque的第一個元素。如果隊列是空 拋出NoSuchElementException
     */
    E getFirst();

    /**
     * Retrieves, but does not remove, the last element of this deque.
     * This method differs from {@link #peekLast peekLast} only in that it
     * throws an exception if this deque is empty.
     *
     * @return the tail of this deque
     * @throws NoSuchElementException if this deque is empty
       檢索並獲得此deque的最後一個元素。如果隊列是空 拋出NoSuchElementException
     */
    E getLast();

    /**
     * Retrieves, but does not remove, the first element of this deque,
     * or returns {@code null} if this deque is empty.
     *
     * @return the head of this deque, or {@code null} if this deque is empty
       檢索並獲得此deque的第一個元素。
     */
    E peekFirst();

    /**
     * Retrieves, but does not remove, the last element of this deque,
     * or returns {@code null} if this deque is empty.
     *
     * @return the tail of this deque, or {@code null} if this deque is empty
       檢索並獲得此deque的最後一個元素。
     */
    E peekLast();

    /**
     * Removes the first occurrence of the specified element from this deque.
     * If the deque does not contain the element, it is unchanged.
     * More formally, removes the first element {@code e} such that
     * {@code Objects.equals(o, e)} (if such an element exists).
     * Returns {@code true} if this deque contained the specified element
     * (or equivalently, if this deque changed as a result of the call).
     *
     * @param o element to be removed from this deque, if present
     * @return {@code true} if an element was removed as a result of this call
     * @throws ClassCastException if the class of the specified element
     *         is incompatible with this deque
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
       從此deque中刪除指定元素的第一個出現。
     */
    boolean removeFirstOccurrence(Object o);

    /**
     * Removes the last occurrence of the specified element from this deque.
     * If the deque does not contain the element, it is unchanged.
     * More formally, removes the last element {@code e} such that
     * {@code Objects.equals(o, e)} (if such an element exists).
     * Returns {@code true} if this deque contained the specified element
     * (or equivalently, if this deque changed as a result of the call).
     *
     * @param o element to be removed from this deque, if present
     * @return {@code true} if an element was removed as a result of this call
     * @throws ClassCastException if the class of the specified element
     *         is incompatible with this deque
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
       從此deque中刪除指定元素的最後一個出現
     */
    boolean removeLastOccurrence(Object o);

    // *** Queue methods ***

    /**
     * Inserts the specified element into the queue represented by this deque
     * (in other words, at the tail of this deque) if it is possible to do so
     * immediately without violating capacity restrictions, returning
     * {@code true} upon success and throwing an
     * {@code IllegalStateException} if no space is currently available.
     * When using a capacity-restricted deque, it is generally preferable to
     * use {@link #offer(Object) offer}.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e the element to add
     * @return {@code true} (as specified by {@link Collection#add})
     * @throws IllegalStateException if the element cannot be added at this
     *         time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
       如果可以在不違反容量限制的情況下立即執行此操作,則將指定的元素插入此雙端隊列表示的隊列中(換句話說,在此雙端隊列的末尾),如果true成功則返回 ,IllegalStateException如果當前沒有可用空間,則拋出 
     */
    boolean add(E e);

    /**
     * Inserts the specified element into the queue represented by this deque
     * (in other words, at the tail of this deque) if it is possible to do so
     * immediately without violating capacity restrictions, returning
     * {@code true} upon success and {@code false} if no space is currently
     * available.  When using a capacity-restricted deque, this method is
     * generally preferable to the {@link #add} method, which can fail to
     * insert an element only by throwing an exception.
     *
     * <p>This method is equivalent to {@link #offerLast}.
     *
     * @param e the element to add
     * @return {@code true} if the element was added to this deque, else
     *         {@code false}
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
       如果可以在不違反容量限制的情況下立即執行此操作,則將指定的元素插入此雙端隊列表示的隊列中(換句話說,在此雙端隊列的末尾),如果true成功,並且false當前沒有可用空間,則將其插入 。
     */
    boolean offer(E e);

    /**
     * Retrieves and removes the head of the queue represented by this deque
     * (in other words, the first element of this deque).
     * This method differs from {@link #poll() poll()} only in that it
     * throws an exception if this deque is empty.
     *
     * <p>This method is equivalent to {@link #removeFirst()}.
     *
     * @return the head of the queue represented by this deque
     * @throws NoSuchElementException if this deque is empty
       檢索並刪除此雙端隊列代表的隊列的頭部,如果隊列爲空,拋出NoSuchElementException
     */
    E remove();

    /**
     * Retrieves and removes the head of the queue represented by this deque
     * (in other words, the first element of this deque), or returns
     * {@code null} if this deque is empty.
     *
     * <p>This method is equivalent to {@link #pollFirst()}.
     *
     * @return the first element of this deque, or {@code null} if
     *         this deque is empty
       檢索並刪除此雙端隊列表示的隊列的頭部
     */
    E poll();

    /**
     * Retrieves, but does not remove, the head of the queue represented by
     * this deque (in other words, the first element of this deque).
     * This method differs from {@link #peek peek} only in that it throws an
     * exception if this deque is empty.
     *
     * <p>This method is equivalent to {@link #getFirst()}.
     *
     * @return the head of the queue represented by this deque
     * @throws NoSuchElementException if this deque is empty
       檢索但不刪除此雙端隊列代表的隊列的頭,如果隊列爲空,拋出NoSuchElementException
     */
    E element();

    /**
     * Retrieves, but does not remove, the head of the queue represented by
     * this deque (in other words, the first element of this deque), or
     * returns {@code null} if this deque is empty.
     *
     * <p>This method is equivalent to {@link #peekFirst()}.
     *
     * @return the head of the queue represented by this deque, or
     *         {@code null} if this deque is empty
       檢索但不刪除此雙端隊列表示的隊列的頭(換句話說,此雙端隊列的第一個元素),null如果此雙端隊列爲空,則返回
     */
    E peek();

    /**
     * Adds all of the elements in the specified collection at the end
     * of this deque, as if by calling {@link #addLast} on each one,
     * in the order that they are returned by the collection's iterator.
     *
     * <p>When using a capacity-restricted deque, it is generally preferable
     * to call {@link #offer(Object) offer} separately on each element.
     *
     * <p>An exception encountered while trying to add an element may result
     * in only some of the elements having been successfully added when
     * the associated exception is thrown.
     *
     * @param c the elements to be inserted into this deque
     * @return {@code true} if this deque changed as a result of the call
     * @throws IllegalStateException if not all the elements can be added at
     *         this time due to insertion restrictions
     * @throws ClassCastException if the class of an element of the specified
     *         collection prevents it from being added to this deque
     * @throws NullPointerException if the specified collection contains a
     *         null element and this deque does not permit null elements,
     *         or if the specified collection is null
     * @throws IllegalArgumentException if some property of an element of the
     *         specified collection prevents it from being added to this deque
       在此雙端隊列的末尾添加指定集合中的所有元素,就像通過調用addLast(E)每個元素一樣,以集合的迭代器返回它們的順序
     */
    boolean addAll(Collection<? extends E> c);

    // *** Stack methods ***

    /**
     * Pushes an element onto the stack represented by this deque (in other
     * words, at the head of this deque) if it is possible to do so
     * immediately without violating capacity restrictions, throwing an
     * {@code IllegalStateException} if no space is currently available.
     *
     * <p>This method is equivalent to {@link #addFirst}.
     *
     * @param e the element to push
     * @throws IllegalStateException if the element cannot be added at this
     *         time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this deque
     如果有可能在不違反容量限制的情況下立即進行操作,則將一個元素推入此雙端隊列表示的堆棧上(換句話說,在此雙端隊列的頭部),如果IllegalStateException當前沒有可用空間,則拋出 。
     */
    void push(E e);

    /**
     * Pops an element from the stack represented by this deque.  In other
     * words, removes and returns the first element of this deque.
     *
     * <p>This method is equivalent to {@link #removeFirst()}.
     *
     * @return the element at the front of this deque (which is the top
     *         of the stack represented by this deque)
     * @throws NoSuchElementException if this deque is empty
       從此雙端隊列表示的堆棧中彈出一個元素,如果隊列爲空,則拋出NoSuchElementException 
     */
    E pop();


    // *** Collection methods ***

    /**
     * Removes the first occurrence of the specified element from this deque.
     * If the deque does not contain the element, it is unchanged.
     * More formally, removes the first element {@code e} such that
     * {@code Objects.equals(o, e)} (if such an element exists).
     * Returns {@code true} if this deque contained the specified element
     * (or equivalently, if this deque changed as a result of the call).
     *
     * <p>This method is equivalent to {@link #removeFirstOccurrence(Object)}.
     *
     * @param o element to be removed from this deque, if present
     * @return {@code true} if an element was removed as a result of this call
     * @throws ClassCastException if the class of the specified element
     *         is incompatible with this deque
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      從此雙端隊列刪除指定元素的第一次出現
     */
    boolean remove(Object o);

    /**
     * Returns {@code true} if this deque contains the specified element.
     * More formally, returns {@code true} if and only if this deque contains
     * at least one element {@code e} such that {@code Objects.equals(o, e)}.
     *
     * @param o element whose presence in this deque is to be tested
     * @return {@code true} if this deque contains the specified element
     * @throws ClassCastException if the class of the specified element
     *         is incompatible with this deque
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         deque does not permit null elements
     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
       返回true此雙端隊列是否包含指定的元素。
     */
    boolean contains(Object o);

    /**
     * Returns the number of elements in this deque.
     *
     * @return the number of elements in this deque
       返回此雙端隊列中的元素數。
     */
    int size();

    /**
     * Returns an iterator over the elements in this deque in proper sequence.
     * The elements will be returned in order from first (head) to last (tail).
     *
     * @return an iterator over the elements in this deque in proper sequence
       以適當的順序返回此雙端隊列中的元素的迭代器
     */
    Iterator<E> iterator();

    /**
     * Returns an iterator over the elements in this deque in reverse
     * sequential order.  The elements will be returned in order from
     * last (tail) to first (head).
     *
     * @return an iterator over the elements in this deque in reverse
     * sequence
       以相反的順序返回此雙端隊列中的元素的迭代器
     */
    Iterator<E> descendingIterator();

}

總結:

   

4.屬性

 

    //元素個數
    transient int size = 0;

    /**
     * Pointer to first node.
       指向第一個節點的指針
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
       指向最後一個節點的指針
     */
    transient Node<E> last;

5.構造函數

 

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

6.內部結構

  LinkedList內部是一個雙端鏈表的結構,結構如下圖:

可以看上面的四個元素,分別就是四個Node對象,可以看到node1所指向的prev上一個節點是空也就是沒有上節點,node4所指向的next節點爲空也就是沒有下一個節點

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

 7.添加元素

   1)add方法(有6個人方法)

  

   add(E):

  

 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++;// 節點數加1
        modCount++;
    }
add(int,E)

  

public void add(int index, E element) {
        checkPositionIndex(index);//校驗索引是否合法

        if (index == size)//添加到鏈表尾部
            linkLast(element);
        else //添加到鏈表中間
            linkBefore(element, node(index));
    }

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

 private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size; //判斷索引是否合法
    }
 void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;//將pred設爲插入節點的上一個節點
        //將新節點的上引用設爲pred,下引用設爲succ
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;//succ的上一個節點設置newNode
        if (pred == null)//新節點的話就是頭結點
            first = newNode;
        else
            pred.next = newNode;// 插入節點的上一個節點的下一個節點引用設爲新節點
        size++;//同上
        modCount++;
    }

addAll(Collection<? extends E>)

 

 //將集合插入到鏈表尾部,即開始索引位置爲size
public boolean addAll(Collection<? extends E> c) {
        return addAll(size, 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;
        //如果插入位置爲尾部,前驅節點爲last,後繼節點爲null
        if (index == size) {
            succ = null;
            pred = last;
        }
        //否則,調用node方法得到後繼節點,在得到前驅節點
        else {
            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的後繼節點
            pred = newNode;//pred重新賦值,以便於下次循環加入
        }
        //如果插入的位置在尾部,重置last節點
        if (succ == null) {
            last = pred;
        }
        //否則,將插入的鏈表和之前的鏈表連接起來
        else {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }

 從上面的代碼可以看到,addAll方法主要分爲4步:
1. 檢查index索引範圍
2. 得到集合數據
3. 得到插入位置的前驅和後繼節點
4. 遍歷數據,將數據插入到指定位置

addFirst

//將元素添加到鏈表頭部
public void addFirst(E e) {
        linkFirst(e);
    }

 private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        //將新節點設爲頭節點
        first = newNode;
        //如果鏈表爲空,last節點也指向該節點
        if (f == null)
            last = newNode;
        else
            f.prev = newNode; //將原先的頭結點指向新節點
        size++; //節點數加1
        modCount++;//記錄修改次數
    }

addLast

 //將元素添加到列表尾部,與add()方法一樣
public void addLast(E e) {
        linkLast(e);
    }

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

offer(E e)方法

//將數據添加到鏈表尾部,其內部調用了add(E e)方法 
public boolean offer(E e) {
        return add(e);
    }

offerLast()與addLast()的區別和offerFirst()和addFirst()的區別一樣,所以這兒就不多說了。其實質是一樣的

總結:

  將數據插入到鏈表尾部
- boolean add(E e):
- void addLast(E e)
- boolean offerLast(E e)
- 將數據插入到鏈表頭部
- void addFirst(E e)
- boolean offerFirst(E e)
- 將數據插入到指定索引位置
- boolean add(int index,E e)

8 檢索操作

    根據位置取數據

     get(int)

//根據指定索引返回數據,如果索引越界,那麼會拋出異常
public E get(int index) {
        //檢查邊界
        checkElementIndex(index);
        return node(index).item;
    }
//獲取頭節點數據
public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }
//獲取頭節點數據
public E element() {
        return getFirst();
    }
public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }
public E element() {
        return getFirst();
    }

LinkedList中有多種方法可以獲得頭節點的數據,實現大同小異,區別在於對鏈表爲空時的處理,是拋出異常還是返回null。主要方法有getFirst()、element()、peek()、peekFirst()、方法。其中getFirst()和element()方法將會在鏈表爲空時,拋出異常

   獲取尾節點數據

//獲取尾節點數據
public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }
public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }

 getLast()方法在鏈表爲空時,會拋出NoSuchElementException,而peekLast()則不會,只是會返回null

根據對象得到索引

  

//返回第一個匹配的索引
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;
    }
//LinkedList可以包含null元素,遍歷方式都是從前往後,一旦匹配了,就返回索引

//返回最後一個匹配的索引
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;
    }

檢查鏈表是否包含某對象

//檢查對象o是否存在於鏈表中
public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
//contains()方法調用了indexOf()方法,只要返回結果不是-1,那就說明該對象存在於鏈表中

檢索操作總結

 檢索操作分爲按照位置得到對象以及按照對象得到位置兩種方式,其中按照對象得到位置的方法有indexOf()和lastIndexOf();按照位置得到對象有如下方法:
- 根據任意位置得到數據的get(int index)方法,當index越界會拋出異常
- 獲得頭節點數據
- getFirst()和element()方法在鏈表爲空時會拋出NoSuchElementException
- peek()和peekFirst()方法在鏈表爲空時會返回null
- 獲得尾節點數據
- getLast()在鏈表爲空時會拋出NoSuchElementException
- peekLast()在鏈表爲空時會返回null

9 刪除操作

    刪除指定對象

      remove


 public E remove() {
        return removeFirst();
    }

public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        //next爲頭結點的下一個節點
        final Node<E> next = f.next;
        //將節點的元素以及引用都設爲null,便於垃圾回收
        f.item = null;
        f.next = null; // help GC
        //修改頭結點爲第二個節點
        first = next;
        //如果第二個節點爲空(當前鏈表只存在第一個元素)
        if (next == null)
            last = null;
        else
            //將第二個節點的上一個引用置爲null
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

remove(int)

 

//刪除指定節點
public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }

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

 remove(object)

public boolean remove(Object o) {
        if (o == 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;
    }

刪除頭節點

   刪除頭節點的對象的方法有很多,包括remove()、removeFirst()、pop()、poll()、pollFirst(),其中前三個方法在鏈表爲空時將拋出NoSuchElementException,後兩個方法在鏈表爲空時將返回null。代碼和上面基本類似,不在做介紹
 

刪除尾節點對象

  刪除尾節點的對象的方法有removeLast()和pollLast()。removeLast的實現如下:

 

public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

 可以看到removeLast()在鏈表爲空時將拋出NoSuchElementException。而pollLast()方法則不會,如下:

 public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

可以看到pollLast()在鏈表爲空時會返回null,而不是拋出異常。

刪除操作總結

  刪除操作由很多種方法,有:
- 按照指定對象刪除:boolean remove(Object o),一次只會刪除一個匹配的對象
- 按照指定位置刪除
- 刪除任意位置的對象:E remove(int index),當index越界時會拋出異常
- 刪除頭節點位置的對象
- 在鏈表爲空時拋出異常:E remove()、E removeFirst()、E pop()
- 在鏈表爲空時返回null:E poll()、E pollFirst()
- 刪除尾節點位置的對象
- 在鏈表爲空時拋出異常:E removeLast()
- 在鏈表爲空時返回null:E pollLast()
 

10迭代操作

 listIterator()

//listIterator實際上是ListItr這個類,下面介紹這個類
 public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }
private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;

        ListItr(int index) {
            // assert isPositionIndex(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++;
            return lastReturned.item;
        }

        public boolean hasPrevious() {
            return nextIndex > 0;
        }
        //獲取前一個節點,將next節點前移
        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++;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (modCount == expectedModCount && nextIndex < size) {
                action.accept(next.item);
                lastReturned = next;
                next = next.next;
                nextIndex++;
            }
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

在ListIterator的構造器中,得到了當前位置的節點,就是變量next。next()方法返回當前節點的值並將next指向其後繼節點,previous()方法返回當前節點的前一個節點的值並將next節點指向其前驅節點。由於Node是一個雙端節點,所以這兒用了一個節點就可以實現從前向後迭代和從後向前迭代。另外在ListIterator初始時,exceptedModCount保存了當前的modCount,如果在迭代期間,有操作改變了鏈表的底層結構,那麼再操作迭代器的方法時將會拋出ConcurrentModificationException
 

總結

LinkedList是基於雙端鏈表的List,其內部的實現源於對鏈表的操作,所以適用於頻繁增加、刪除的情況;該類不是線程安全的;另外,由於LinkedList實現了Queue接口,所以LinkedList不止有隊列的接口,還有棧的接口,可以使用LinkedList作爲隊列和棧的實現。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章