Java 集合框架05-LinkedList的详细介绍

简介: 上篇我们介绍完了fail-fast 机制,下面我们将接着介绍List的另一个实现类LinkedList。

上篇我们介绍完了fail-fast 机制,下面我们将接着介绍List的另一个实现类LinkedList。

我们将从以下几个方面介绍


1.LinkedList的介绍

2.LinkedList的数据结构

3.LinkedList的源码分析(基于JDK1.8)

4.LinkedList的遍历方式

5.LinkedList的示例

6.ArrayList与LinkedList的区别


LinkedList的介绍


LinkedList的定义

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable{}


LinkedList是一个继承于AbstractSequentialList的双向链表,可以被当作堆栈,双向队列,队列进行操作。

LinkedList实现了List,可以被当作队列进行操作。

LinkedList 实现了Deque,可以被当作双向队列进行操作。

LinkedList实现了Cloneable,可以被克隆。

LinkedList实现了java.io.Serializable,可以被序列化

LinkedList是线程不安全的。

PS:


LinkedList的数据结构

LinkedList的API

LinkedList的API
boolean       add(E object)
void          add(int location, E object)
boolean       addAll(Collection<? extends E> collection)
boolean       addAll(int location, Collection<? extends E> collection)
void          addFirst(E object)
void          addLast(E object)
void          clear()
Object        clone()
boolean       contains(Object object)
Iterator<E>   descendingIterator()
E             element()
E             get(int location)
E             getFirst()
E             getLast()
int           indexOf(Object object)
int           lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
boolean       offer(E o)
boolean       offerFirst(E e)
boolean       offerLast(E e)
E             peek()
E             peekFirst()
E             peekLast()
E             poll()
E             pollFirst()
E             pollLast()
E             pop()
void          push(E e)
E             remove()
E             remove(int location)
boolean       remove(Object object)
E             removeFirst()
boolean       removeFirstOccurrence(Object o)
E             removeLast()
boolean       removeLastOccurrence(Object o)
E             set(int location, E object)
int           size()
<T> T[]       toArray(T[] contents)
Object[]     toArray()


LinkedList的类图如下

f367fe6776e5150079a6094281e0218f_SouthEast.jpg

LinkedList 本质上是一个双向链表。

LinkedList 包含两个重要的成员 header和size。

header是双向链表的表头,是双向链表节点所对应的类Entry的实例。Entry中包含成员变量: previous, next, element。其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。

 size是双向链表中节点的个数。


LinkedList源码解析(基于jdk 1.8)

为了更好的了解LinkedList的原理,下面我们对LinkedList的源码进行分析下。

在阅读源码之前,我们先对LinkedList的整体实现进行大致说明:

LinkedList 实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,随机访问效率比较低。

既然LinkedList是通过双向链表的,但是它也实现了List 接口(也就是说它实现了get(int index)和remove(int index) 等通过索引值来获取,移除节点的函数)。

LinkedList 是如何实现List的这些接口的,如何将双向链表和索引值联系起来的?

实际原理是,它是通过一个计数索引值来实现的,例如,当我们调用get(int index)时,首先index与双向链表长度的1/2 进行比较。如果前者大,则从链表头开始往后查找,直到找到location位置;否则,从链表末尾开始先前查找,直到找到location位置。

这就是双向链表好索引值联系起来的方法。

接下来开始阅读源码


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.(初始化一个空的list)

    */

   public LinkedList() {

   }


   /**

    * Constructs a list containing the elements of the specified

    * collection, in the order they are returned by the collection's

    * iterator.

    * 包含“集合”的构造函数,创建一个包含"集合"的LinkedList

    * @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);

   }


   /**

    * 获取第一个元素

    * Links e as first element.

    */

   private void linkFirst(E e) {

       final Node<E> f = first;

       final Node<E> newNode = new Node<>(null, e, f);

       first = newNode;

       if (f == null)

           last = newNode;

       else

           f.prev = newNode;

       size++;

       modCount++;

   }


   /**

    * 获取最后一个元素

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

   }


   /**

    * Inserts element e before non-null Node succ.

    * 在节点succ之前增加元素

    */

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

   }


   /**

    * Unlinks non-null first node f.

    *

    */

   private E unlinkFirst(Node<E> f) {

       // assert f == first && f != null;

       final E element = f.item;

       final Node<E> next = f.next;

       f.item = null;

       f.next = null; // help GC

       first = next;

       if (next == null)

           last = null;

       else

           next.prev = null;

       size--;

       modCount++;

       return element;

   }


   /**

    * Unlinks non-null last node l.

    */

   private E unlinkLast(Node<E> l) {

       // assert l == last && l != null;

       final E element = l.item;

       final Node<E> prev = l.prev;

       l.item = null;

       l.prev = null; // help GC

       last = prev;

       if (prev == null)

           first = null;

       else

           prev.next = null;

       size--;

       modCount++;

       return element;

   }


   /**

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

   }


   /**

    * Returns the first element in this list.

    * 返回该集合的第一个元素

    * @return the first element in this list

    * @throws NoSuchElementException if this list is empty

    */

   public E getFirst() {

       final Node<E> f = first;

       if (f == null)

           throw new NoSuchElementException();

       return f.item;

   }


   /**

    * Returns the last element in this list.

    * 返回该集合的最后一个元素

    * @return the last element in this list

    * @throws NoSuchElementException if this list is empty

    */

   public E getLast() {

       final Node<E> l = last;

       if (l == null)

           throw new NoSuchElementException();

       return l.item;

   }


   /**

    * Removes and returns the first element from this list.

    * 从集合中移除掉第一个元素

    * @return the first element from this list

    * @throws NoSuchElementException if this list is empty

    */

   public E removeFirst() {

       final Node<E> f = first;

       if (f == null)

           throw new NoSuchElementException();

       return unlinkFirst(f);

   }


   /**

    * Removes and returns the last element from this list.

    *  从集合中移除掉最后一个元素

    * @return the last element from this list

    * @throws NoSuchElementException if this list is empty

    */

   public E removeLast() {

       final Node<E> l = last;

       if (l == null)

           throw new NoSuchElementException();

       return unlinkLast(l);

   }


   /**

    * Inserts the specified element at the beginning of this list.

    * 从该集合中插入一个元素,插入为第一个

    * @param e the element to add

    */

   public void addFirst(E e) {

       linkFirst(e);

   }


   /**

    * Appends the specified element to the end of this list.

    * 从该集合中插入一个元素,插入为最后一个

    * <p>This method is equivalent to {@link #add}.

    *

    * @param e the element to add

    */

   public void addLast(E e) {

       linkLast(e);

   }


   /**

    * Returns {@code true} if this list contains the specified element.

    * 查找集合中是否某元素

    */

   public boolean contains(Object o) {

       return indexOf(o) != -1;

   }


   /**

    * Returns the number of elements in this list.

    *  返回集合的大小

    * @return the number of elements in this list

    */

   public int size() {

       return size;

   }


   /**

    * Appends the specified element to the end of this list.

    * 将元素添加到集合尾部

    */

   public boolean add(E e) {

       linkLast(e);

       return true;

   }


   /**

    * Removes the first occurrence of the specified element from this list,

    * if it is present.  If this list does not contain the element, it is

    * unchanged.  More formally, removes the element with the lowest index

    * {@code i} such that

    * 从集合中移除某个元素

    */

   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;

   }


   /**

    * Appends all of the elements in the specified collection to the end of

    * 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.)

    * 将Collection c 添加到该集合中,添加到集合尾部

    */

   public boolean addAll(Collection<? extends E> c) {

       return addAll(size, c);

   }


   /**

    * Inserts all of the elements in the specified collection into this

    * list, starting at the specified position.  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 the list in the order that they are returned by the

    * specified collection's iterator.

    *  将Collection c 添加到该集合中,添加到集合指定位置

    */

   public boolean addAll(int index, Collection<? extends E> c) {

       checkPositionIndex(index);


       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 {

           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;

       modCount++;

       return true;

   }


   /**

    * Removes all of the elements from this list.

    * The list will be empty after this call returns.

    * 从集合中移除掉所有元素

    */

   public void clear() {

       for (Node<E> x = first; x != null; ) {

           Node<E> next = x.next;

           x.item = null;

           x.next = null;

           x.prev = null;

           x = next;

       }

       first = last = null;

       size = 0;

       modCount++;

   }



   // Positional Access Operations


   /**

    * Returns the element at the specified position in this list.

    * 返回元素在集合中的位置

    * @param index index of the element to return

    * @return the element at the specified position in this list

    * @throws IndexOutOfBoundsException {@inheritDoc}

    */

   public E get(int index) {

       checkElementIndex(index);

       return node(index).item;

   }


   /**

    * Replaces the element at the specified position in this list with the

    * specified element.

    * 替换指定位置的元素的值

    */

   public E set(int index, E element) {

       checkElementIndex(index);

       Node<E> x = node(index);

       E oldVal = x.item;

       x.item = element;

       return oldVal;

   }


   /**

    * Inserts the specified element at the specified position in this list.

    * Shifts the element currently at that position (if any) and any

    * subsequent elements to the right (adds one to their indices).

    * 将元素添加到集合中的指定位置

    */

   public void add(int index, E element) {

       checkPositionIndex(index);


       if (index == size)

           linkLast(element);

else
            linkBefore(element, node(index));
    }
    /**
     * 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.
     * 移除指定位置的元素
     */
    public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }
    /**
     * Tells if the argument is the index of an existing element.
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }
    /**
     * Tells if the argument is the index of a valid position for an
     * iterator or an add operation.
     */
    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }
    /**
     * Constructs an IndexOutOfBoundsException detail message.
     * Of the many possible refactorings of the error handling code,
     * this "outlining" performs best with both server and client VMs.
     */
    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));
    }
    /**
     * Returns the (non-null) Node at the specified element 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;
        }
    }
    // Search Operations
    /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index {@code i} such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @return the index of the first occurrence of the specified element in
     *         this list, or -1 if this list does not contain the element
     */
    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;
    }
    /**
     * Returns the index of the last occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the highest index {@code i} such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @return the index of the last occurrence of the specified element in
     *         this list, or -1 if this list does not contain the element
     */
    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;
    }
    // Queue operations.
    /**
     * Retrieves, but does not remove, the head (first element) of this list.
     *
     * @return the head of this list, or {@code null} if this list is empty
     * @since 1.5
     */
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }
    /**
     * Retrieves, but does not remove, the head (first element) of this list.
     *
     * @return the head of this list
     * @throws NoSuchElementException if this list is empty
     * @since 1.5
     */
    public E element() {
        return getFirst();
    }
    /**
     * Retrieves and removes the head (first element) of this list.
     *
     * @return the head of this list, or {@code null} if this list is empty
     * @since 1.5
     */
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    /**
     * Retrieves and removes the head (first element) of this list.
     *
     * @return the head of this list
     * @throws NoSuchElementException if this list is empty
     * @since 1.5
     */
    public E remove() {
        return removeFirst();
    }
    /**
     * Adds the specified element as the tail (last element) of this list.
     *
     * @param e the element to add
     * @return {@code true} (as specified by {@link Queue#offer})
     * @since 1.5
     */
    public boolean offer(E e) {
        return add(e);
    }
    // Deque operations
    /**
     * Inserts the specified element at the front of this list.
     *
     * @param e the element to insert
     * @return {@code true} (as specified by {@link Deque#offerFirst})
     * @since 1.6
     */
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
    /**
     * Inserts the specified element at the end of this list.
     *
     * @param e the element to insert
     * @return {@code true} (as specified by {@link Deque#offerLast})
     * @since 1.6
     */
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
    /**
     * Retrieves, but does not remove, the first element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the first element of this list, or {@code null}
     *         if this list is empty
     * @since 1.6
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }
    /**
     * Retrieves, but does not remove, the last element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the last element of this list, or {@code null}
     *         if this list is empty
     * @since 1.6
     */
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }
    /**
     * Retrieves and removes the first element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the first element of this list, or {@code null} if
     *     this list is empty
     * @since 1.6
     */
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    /**
     * Retrieves and removes the last element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the last element of this list, or {@code null} if
     *     this list is empty
     * @since 1.6
     */
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }
    /**
     * Pushes an element onto the stack represented by this list.  In other
     * words, inserts the element at the front of this list.
     *
     * <p>This method is equivalent to {@link #addFirst}.
     *
     * @param e the element to push
     * @since 1.6
     */
    public void push(E e) {
        addFirst(e);
    }
    /**
     * Pops an element from the stack represented by this list.  In other
     * words, removes and returns the first element of this list.
     *
     * <p>This method is equivalent to {@link #removeFirst()}.
     *
     * @return the element at the front of this list (which is the top
     *         of the stack represented by this list)
     * @throws NoSuchElementException if this list is empty
     * @since 1.6
     */
    public E pop() {
        return removeFirst();
    }
    /**
     * Removes the first occurrence of the specified element in this
     * list (when traversing the list from head to tail).  If the list
     * does not contain the element, it is unchanged.
     *
     * @param o element to be removed from this list, if present
     * @return {@code true} if the list contained the specified element
     * @since 1.6
     */
    public boolean removeFirstOccurrence(Object o) {
        return remove(o);
    }
    /**
     * Removes the last occurrence of the specified element in this
     * list (when traversing the list from head to tail).  If the list
     * does not contain the element, it is unchanged.
     *
     * @param o element to be removed from this list, if present
     * @return {@code true} if the list contained the specified element
     * @since 1.6
     */
    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;
    }
    /**
     * Returns a list-iterator of the elements in this list (in proper
     * sequence), starting at the specified position in the list.
     * Obeys the general contract of {@code List.listIterator(int)}.<p>
     *
     * The list-iterator is <i>fail-fast</i>: if the list is structurally
     * modified at any time after the Iterator is created, in any way except
     * through the list-iterator's own {@code remove} or {@code add}
     * methods, the list-iterator will throw a
     * {@code ConcurrentModificationException}.  Thus, in the face of
     * concurrent modification, the iterator fails quickly and cleanly, rather
     * than risking arbitrary, non-deterministic behavior at an undetermined
     * time in the future.
     *
     * @param index index of the first element to be returned from the
     *              list-iterator (by a call to {@code next})
     * @return a ListIterator of the elements in this list (in proper
     *         sequence), starting at the specified position in the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see List#listIterator(int)
     */
    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;
        }
        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();
        }
    }
     // 双向链表的节点所对应的数据结构。
          // 包含3部分:上一节点,下一节点,当前节点值。
    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;
        }
    }
    /**
     * @since 1.6
     */
    public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }
    /**
     * Adapter to provide descending iterators via ListItr.previous
     * 反向迭代器
     */
    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(e);
        }
    }
    /**
     * Returns a shallow copy of this {@code LinkedList}. (The elements
     * themselves are not cloned.)
     *  克隆函数,返回LinkedList的克隆对象
    */
    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;
    }
    /**
     * Returns an array containing all of the elements in this list
     * in proper sequence (from first to last element).
     * 返回LinkedList的数组Object[]
     */
    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;
    }
    /**
     * 返回LinkedList的模板数组。所谓模板数组,即可以将T设为任意的数据类型
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // 若数组a的大小<LinkedList的元素个数,(意味着数组a不足以容纳LinkedList中的全部元素)
        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;
    /**
     * Saves the state of this {@code LinkedList} instance to a stream
     * (that is, serializes it).
     *// java.io.Serializable的写入函数
     * 将LinkedList的“容量,所有的元素值”都写入到输出流中
     */
    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);
    }
    /**
     * Reconstitutes this {@code LinkedList} instance from a stream
     * (that is, deserializes it).
     */
    @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());
    }
    }
     }
    /**
     * Retrieves, but does not remove, the head (first element) of this list.
     *
     * @return the head of this list
     * @throws NoSuchElementException if this list is empty
     * @since 1.5
     */
    public E element() {
        return getFirst();
    }
    /**
     * Retrieves and removes the head (first element) of this list.
     *
     * @return the head of this list, or {@code null} if this list is empty
     * @since 1.5
     */
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    /**
     * Retrieves and removes the head (first element) of this list.
     *
     * @return the head of this list
     * @throws NoSuchElementException if this list is empty
     * @since 1.5
     */
    public E remove() {
        return removeFirst();
    }
    /**
     * Adds the specified element as the tail (last element) of this list.
     *
     * @param e the element to add
     * @return {@code true} (as specified by {@link Queue#offer})
     * @since 1.5
     */
    public boolean offer(E e) {
        return add(e);
    }
    // Deque operations
    /**
     * Inserts the specified element at the front of this list.
     *
     * @param e the element to insert
     * @return {@code true} (as specified by {@link Deque#offerFirst})
     * @since 1.6
     */
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
    /**
     * Inserts the specified element at the end of this list.
     *
     * @param e the element to insert
     * @return {@code true} (as specified by {@link Deque#offerLast})
     * @since 1.6
     */
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
    /**
     * Retrieves, but does not remove, the first element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the first element of this list, or {@code null}
     *         if this list is empty
     * @since 1.6
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }
    /**
     * Retrieves, but does not remove, the last element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the last element of this list, or {@code null}
     *         if this list is empty
     * @since 1.6
     */
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }
    /**
     * Retrieves and removes the first element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the first element of this list, or {@code null} if
     *     this list is empty
     * @since 1.6
     */
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    /**
     * Retrieves and removes the last element of this list,
     * or returns {@code null} if this list is empty.
     *
     * @return the last element of this list, or {@code null} if
     *     this list is empty
     * @since 1.6
     */
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }
    /**
     * Pushes an element onto the stack represented by this list.  In other
     * words, inserts the element at the front of this list.
     *
     * <p>This method is equivalent to {@link #addFirst}.
     *
     * @param e the element to push
     * @since 1.6
     */
    public void push(E e) {
        addFirst(e);
    }
    /**
     * Pops an element from the stack represented by this list.  In other
     * words, removes and returns the first element of this list.
     *
     * <p>This method is equivalent to {@link #removeFirst()}.
     *
     * @return the element at the front of this list (which is the top
     *         of the stack represented by this list)
     * @throws NoSuchElementException if this list is empty
     * @since 1.6
     */
    public E pop() {
        return removeFirst();
    }
    /**
     * Removes the first occurrence of the specified element in this
     * list (when traversing the list from head to tail).  If the list
     * does not contain the element, it is unchanged.
     *
     * @param o element to be removed from this list, if present
     * @return {@code true} if the list contained the specified element
     * @since 1.6
     */
    public boolean removeFirstOccurrence(Object o) {
        return remove(o);
    }
    /**
     * Removes the last occurrence of the specified element in this
     * list (when traversing the list from head to tail).  If the list
     * does not contain the element, it is unchanged.
     *
     * @param o element to be removed from this list, if present
     * @return {@code true} if the list contained the specified element
     * @since 1.6
     */
    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;
    }
    /**
     * Returns a list-iterator of the elements in this list (in proper
     * sequence), starting at the specified position in the list.
     * Obeys the general contract of {@code List.listIterator(int)}.<p>
     *
     * The list-iterator is <i>fail-fast</i>: if the list is structurally
     * modified at any time after the Iterator is created, in any way except
     * through the list-iterator's own {@code remove} or {@code add}
     * methods, the list-iterator will throw a
     * {@code ConcurrentModificationException}.  Thus, in the face of
     * concurrent modification, the iterator fails quickly and cleanly, rather
     * than risking arbitrary, non-deterministic behavior at an undetermined
     * time in the future.
     *
     * @param index index of the first element to be returned from the
     *              list-iterator (by a call to {@code next})
     * @return a ListIterator of the elements in this list (in proper
     *         sequence), starting at the specified position in the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see List#listIterator(int)
     */
    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;
        }
        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();
        }
    }
     // 双向链表的节点所对应的数据结构。
          // 包含3部分:上一节点,下一节点,当前节点值。
    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;
        }
    }
    /**
     * @since 1.6
     */
    public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }
    /**
     * Adapter to provide descending iterators via ListItr.previous
     * 反向迭代器
     */
    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(e);
        }
    }
    /**
     * Returns a shallow copy of this {@code LinkedList}. (The elements
     * themselves are not cloned.)
     *  克隆函数,返回LinkedList的克隆对象
    */
    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;
    }
    /**
     * Returns an array containing all of the elements in this list
     * in proper sequence (from first to last element).
     * 返回LinkedList的数组Object[]
     */
    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;
    }
    /**
     * 返回LinkedList的模板数组。所谓模板数组,即可以将T设为任意的数据类型
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // 若数组a的大小<LinkedList的元素个数,(意味着数组a不足以容纳LinkedList中的全部元素)
        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;
    /**
     * Saves the state of this {@code LinkedList} instance to a stream
     * (that is, serializes it).
     *// java.io.Serializable的写入函数
     * 将LinkedList的“容量,所有的元素值”都写入到输出流中
     */
    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);
    }
    /**
     * Reconstitutes this {@code LinkedList} instance from a stream
     * (that is, deserializes it).
     */
    @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());
    }
    }


总结:


LinkedList 实际上是通过双向链表来实现的。它包含一个非常重要内部类Node

Node是LinkedList对应的数据结构,该数据结构包含的属性有:当前节点对应的值,上一节点,下一节点。

从LinkedList的实现来看,其不存在容量不足的问题

LinkedList的克隆函数,即是将所有元素克隆到一个新的LinkedList对象中。

LinkedList实现java.io.Serializable,当写入输出流时,先写入容量,然后,写入每一个受保护的变量,读取输入流时,

先读取容量,然后,读取每一个元素。

由于LinkedList实现了Deque,而Deque接口提供了在双端队列两端访问元素的方法,提供了插入,移除和检查元素的方法。每种方法都存在两种形式,一种形式在操作失败时抛出异常,一种形式是返回特殊的值(null或者false)。

引用

http://blog.csdn.net/eson_15/article/details/51145788

http://www.cnblogs.com/skywang12345/p/3308807.html


相关文章
|
19天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
10天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
527 8
|
8天前
|
算法 Java
Java项目不使用框架如何实现限流?
Java项目不使用框架如何实现限流?
19 2
|
9天前
|
存储 安全 Java
Java 常用集合分类
Java 常用集合分类
13 2
|
14天前
|
Kubernetes Java Android开发
用 Quarkus 框架优化 Java 微服务架构的设计与实现
Quarkus 是专为 GraalVM 和 OpenJDK HotSpot 设计的 Kubernetes Native Java 框架,提供快速启动、低内存占用及高效开发体验,显著优化了 Java 在微服务架构中的表现。它采用提前编译和懒加载技术实现毫秒级启动,通过优化类加载机制降低内存消耗,并支持多种技术和框架集成,如 Kubernetes、Docker 及 Eclipse MicroProfile,助力开发者轻松构建强大微服务应用。例如,在电商场景中,可利用 Quarkus 快速搭建商品管理和订单管理等微服务,提升系统响应速度与稳定性。
30 5
|
14天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
1月前
|
Java 数据库连接 Apache
Java进阶-主流框架总结与详解
这些仅仅是 Java 众多框架中的一部分。每个框架都有其特定的用途和优势,了解并熟练运用这些框架,对于每一位 Java 开发者来说都至关重要。同时,选择合适框架的关键在于理解框架的设计哲学、核心功能及其在项目中的应用场景。随着技术的不断进步,这些框架也在不断更新和迭代以适应新的开发者需求。
39 1
|
2月前
|
存储 算法 Java
Java中的集合框架深度解析与实践
【8月更文挑战第31天】在Java编程的海洋中,集合框架扮演着不可或缺的角色。本文将带你领略Java集合框架的魅力,从理论到实践,深入浅出地探索List、Set和Map等核心接口的使用技巧。我们将通过具体代码示例,展示如何在日常开发中高效运用这些工具,让你的代码更加优雅和高效。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往Java集合世界的大门。
|
2月前
|
存储 人工智能 Java
JAVA集合
【8月更文挑战第31天】
|
2月前
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。
下一篇
无影云桌面