java1.7集合源码阅读:LinkedList

时间:2022-09-17 19:33:53

先看看类定义:

1 public class LinkedList<E>
2 extends AbstractSequentialList<E>
3 implements List<E>, Deque<E>, Cloneable, java.io.Serializable
4 {
5 .......
6 }
LinkedList与ArrayList相比,LinkedList不再实现RandomAccess接口,表明不支持快速随机访问数据,但实现了Deque接口,可当队列使用,Deque继承自Queue,接口定义:
 1 public interface Queue<E> extends Collection<E> {
2 void addFirst(E e);
3 void addLast(E e);
4 boolean offerFirst(E e);
5 boolean offerLast(E e);
6 E removeFirst();
7 E removeLast();
8 E pollFirst();
9 E pollLast();
10 E getFirst();
11 E getLast();
12 E peekFirst();
13 E peekLast();
14 boolean removeFirstOccurrence(Object o);
15 boolean removeLastOccurrence(Object o);
16 boolean add(E e);
17 boolean offer(E e);
18 E remove();
19 E poll();
20 E element();
21 E peek();
22 void push(E e);
23 boolean remove(Object o);
24 boolean contains(Object o);
25 public int size();
26 Iterator<E> iterator();
27 Iterator<E> descendingIterator();
28 }

看看LinkedList的两个属性,一个头节点,一个末节点:
 1     /**
2 * Pointer to first node.
3 * Invariant: (first == null && last == null) ||
4 * (first.prev == null && first.item != null)
5 */
6 transient Node<E> first;
7
8 /**
9 * Pointer to last node.
10 * Invariant: (first == null && last == null) ||
11 * (last.next == null && last.item != null)
12 */
13 transient Node<E> last;

在看看Node的定义:

 1     private static class Node<E> {
2 E item;
3 Node<E> next;
4 Node<E> prev;
5
6 Node(Node<E> prev, E element, Node<E> next) {
7 this.item = element;
8 this.next = next;
9 this.prev = prev;
10 }
11 }

Node中保存着存入集合的对象,同时也保存着上一个节点和下一个节点,由此可知,LinkedList 内部采用的是双向链表结构。

再看看CRUD操作:

add:

 1     /**
2 * Appends the specified element to the end of this list.
3 *
4 * <p>This method is equivalent to {@link #addLast}.
5 *
6 * @param e element to be appended to this list
7 * @return {@code true} (as specified by {@link Collection#add})
8 */
9 public boolean add(E e) {
10 linkLast(e); //last节点后拼接一个节点
11 return true;
12 }
13 /**
14 * Links e as last element.
15 */
16 void linkLast(E e) {
17 final Node<E> l = last;
18 final Node<E> newNode = new Node<>(l, e, null);
19 last = newNode; // 将last节点指向当前新创建的节点,新节点变为last节点,原last节点的下一个节点指向最新的last节点
20    if (l == null)
21     first = newNode;
22   else
23     l.next = newNode;
24   size++;
25   modCount++;
26 }

 与linkLast对应的还有linkFirst:

 1     /**
2 * Links e as first element.
3 */将元素添加到首节点
4 private void linkFirst(E e) {
5 final Node<E> f = first;
6 final Node<E> newNode = new Node<>(null, e, f);
7 first = newNode;
8 if (f == null)
9 last = newNode;
10 else
11 f.prev = newNode;
12 size++;
13 modCount++;
14 }

既然存在在对尾、队尾添加元素,那么是不是也应该存在在指定某个元素之前或之后添加元素呢,是的,的确存在:

 1     /**
2 * Inserts element e before non-null Node succ.
3 */
4 void linkBefore(E e, Node<E> succ) {
5 // assert succ != null;
6 final Node<E> pred = succ.prev;
7 final Node<E> newNode = new Node<>(pred, e, succ);
8 succ.prev = newNode;
9 if (pred == null)
10 first = newNode;
11 else
12 pred.next = newNode;
13 size++;
14 modCount++;
15 }

与此同时也还存在另外两个方法,一个是在指定节点位置添加元素,另一个是将指定位置的元素修改成当前元素:

 1    /**
2 * Replaces the element at the specified position in this list with the
3 * specified element.
4 *
5 * @param index index of the element to replace
6 * @param element element to be stored at the specified position
7 * @return the element previously at the specified position
8 * @throws IndexOutOfBoundsException {@inheritDoc}
9 */
10 public E set(int index, E element) { //指定位置的元素修改成当前元素
11 checkElementIndex(index);
12 Node<E> x = node(index);
13 E oldVal = x.item;
14 x.item = element;
15 return oldVal;
16 }
17
18 /**
19 * Inserts the specified element at the specified position in this list.
20 * Shifts the element currently at that position (if any) and any
21 * subsequent elements to the right (adds one to their indices).
22 *
23 * @param index index at which the specified element is to be inserted
24 * @param element element to be inserted
25 * @throws IndexOutOfBoundsException {@inheritDoc}
26 */
27 public void add(int index, E element) { //指定节点位置添加元素
28 checkPositionIndex(index);
29
30 if (index == size)
31 linkLast(element);
32 else
33 linkBefore(element, node(index));
34 }

linkedList  虽然提供了get(index) 方法,但并不没有ArrayList那样高效的获取,而是变量整个数据结构,此时,做了一个优化,根据index判断元素是在链表的前端还是后端,如果是后端,则从队尾开始遍历:

 1     /**
2 * Returns the element at the specified position in this list.
3 *
4 * @param index index of the element to return
5 * @return the element at the specified position in this list
6 * @throws IndexOutOfBoundsException {@inheritDoc}
7 */
8 public E get(int index) {
9 checkElementIndex(index);
10 return node(index).item;
11 }
12 /**
13 * Returns the (non-null) Node at the specified element index.
14 */
15 Node<E> node(int index) {
16 // assert isElementIndex(index);
17
18 if (index < (size >> 1)) {
19 Node<E> x = first;
20 for (int i = 0; i < index; i++)
21 x = x.next;
22 return x;
23 } else {
24 Node<E> x = last;
25 for (int i = size - 1; i > index; i--)
26 x = x.prev;
27 return x;
28 }
29 }

获取对首或队尾元素就简单了,直接返回对首或队尾元素就ok了:

 1   /**
2 * Returns the first element in this list.
3 *
4 * @return the first element in this list
5 * @throws NoSuchElementException if this list is empty
6 */
7 public E getFirst() {
8 final Node<E> f = first;
9 if (f == null)
10 throw new NoSuchElementException();
11 return f.item;
12 }
13
14 /**
15 * Returns the last element in this list.
16 *
17 * @return the last element in this list
18 * @throws NoSuchElementException if this list is empty
19 */
20 public E getLast() {
21 final Node<E> l = last;
22 if (l == null)
23 throw new NoSuchElementException();
24 return l.item;
25 }

LinkedList 无参remove方法,是直接删除队首元素:

 1   /**
2 * Retrieves and removes the head (first element) of this list.
3 *
4 * @return the head of this list
5 * @throws NoSuchElementException if this list is empty
6 * @since 1.5
7 */
8 public E remove() {
9 return removeFirst();
10 }
11 /**
12 * Removes and returns the first element from this list.
13 *
14 * @return the first element from this list
15 * @throws NoSuchElementException if this list is empty
16 */
17 public E removeFirst() {
18 final Node<E> f = first;
19 if (f == null)
20 throw new NoSuchElementException();
21 return unlinkFirst(f);
22 }
23 /**
24 * Unlinks non-null first node f.
25 */
26 private E unlinkFirst(Node<E> f) { //将对首元素设置null,将对首的下一元素作为对首元素
27 // assert f == first && f != null;
28 final E element = f.item;
29 final Node<E> next = f.next;
30 f.item = null;
31 f.next = null; // help GC
32 first = next;
33 if (next == null)
34 last = null;
35 else
36 next.prev = null;
37 size--;
38 modCount++;
39 return element;
40 }

remove(Object),变量整个数据结构删除:

 1   /**
2 * Removes the first occurrence of the specified element from this list,
3 * if it is present. If this list does not contain the element, it is
4 * unchanged. More formally, removes the element with the lowest index
5 * {@code i} such that
6 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
7 * (if such an element exists). Returns {@code true} if this list
8 * contained the specified element (or equivalently, if this list
9 * changed as a result of the call).
10 *
11 * @param o element to be removed from this list, if present
12 * @return {@code true} if this list contained the specified element
13 */
14 public boolean remove(Object o) {
15 if (o == null) {//先判断是否是空值
16 for (Node<E> x = first; x != null; x = x.next) {
17 if (x.item == null) {
18 unlink(x);
19 return true;
20 }
21 }
22 } else {
23 for (Node<E> x = first; x != null; x = x.next) {
24 if (o.equals(x.item)) {
25 unlink(x);
26 return true;
27 }
28 }
29 }
30 return false;
31 }

linkedList实现了队列接口,使用中也可以直接当队列用:

 1    /**
2 * Adds the specified element as the tail (last element) of this list.
3 *
4 * @param e the element to add
5 * @return {@code true} (as specified by {@link Queue#offer})
6 * @since 1.5
7 */
8 public boolean offer(E e) {
9 return add(e);
10 }
11
12 // Deque operations
13 /**
14 * Inserts the specified element at the front of this list.
15 *
16 * @param e the element to insert
17 * @return {@code true} (as specified by {@link Deque#offerFirst})
18 * @since 1.6
19 */
20 public boolean offerFirst(E e) {
21 addFirst(e);
22 return true;
23 }
24
25 /**
26 * Inserts the specified element at the end of this list.
27 *
28 * @param e the element to insert
29 * @return {@code true} (as specified by {@link Deque#offerLast})
30 * @since 1.6
31 */
32 public boolean offerLast(E e) {
33 addLast(e);
34 return true;
35 }

linkedList 还提供了几个方法,可以直接通过peek方法获取元素,需要注意的是获取之后并不会从队列中删除该元素:

 1    /**
2 * Retrieves, but does not remove, the first element of this list,
3 * or returns {@code null} if this list is empty.
4 *
5 * @return the first element of this list, or {@code null}
6 * if this list is empty
7 * @since 1.6
8 */
9 public E peekFirst() {
10 final Node<E> f = first;
11 return (f == null) ? null : f.item;
12 }
13
14 /**
15 * Retrieves, but does not remove, the last element of this list,
16 * or returns {@code null} if this list is empty.
17 *
18 * @return the last element of this list, or {@code null}
19 * if this list is empty
20 * @since 1.6
21 */
22 public E peekLast() {
23 final Node<E> l = last;
24 return (l == null) ? null : l.item;
25 }

与peek对应的还有poll方法,同样是获取元素,不同点在于,获取元素之后,该元素将会从队列中删除。

 1   /**
2 * Retrieves and removes the first element of this list,
3 * or returns {@code null} if this list is empty.
4 *
5 * @return the first element of this list, or {@code null} if
6 * this list is empty
7 * @since 1.6
8 */
9 public E pollFirst() {
10 final Node<E> f = first;
11 return (f == null) ? null : unlinkFirst(f);
12 }
13
14 /**
15 * Retrieves and removes the last element of this list,
16 * or returns {@code null} if this list is empty.
17 *
18 * @return the last element of this list, or {@code null} if
19 * this list is empty
20 * @since 1.6
21 */
22 public E pollLast() {
23 final Node<E> l = last;
24 return (l == null) ? null : unlinkLast(l);
25 }

LinkedList提供了多种操作数据集合的方法,但最重要的一点就是,整个是实现是非线程安全的,在多线程下需要进行同步处理,或者使用并发包中的对应实现类。