初始化
构造方法是个无参方法 + 有初始化数据集合参数的方法
public LinkedList() {}public LinkedList(Collection<? extends E> c) {this();addAll(c);}
内部有一个头节点、一个尾节点,以及一个 size 变量记录长度,每个节点记录了后续节点、前缀节点,双向链表
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;}}transient int size = 0;transient Node<E> first;transient Node<E> last;
size()
isEmpty()
contains(Object o)
判断 indexOf(o) != -1,indexOf(o) 逻辑就是简单的链表遍历
public int indexOf(Object o) {int index = 0;if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null)return index;index++;}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item))return index;index++;}}return -1;}
add(E e)
调用添加到链表末位方法 linkLast
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;elsel.next = newNode;size++;modCount++;}
正常添加节点操作,只是判断了下链表是否空的,空的话头节点指向这个节点
remove(Object o)
遍历找到节点后调用 unlink 方法
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;}
addAll(Collection<? extends E> c);
调用了 addAll(size, 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;elsepred.next = newNode;pred = newNode;}if (succ == null) {last = pred;} else {pred.next = succ;succ.prev = pred;}size += numNew;modCount++;return true;}
就是构建新链表插入的过程,只不过区分了是末位插入,还是中间插入
addAll(int index, Collection<? extends E> c)
clear()
public void clear() {// Clearing all of the links between nodes is "unnecessary", but:// - helps a generational GC if the discarded nodes inhabit// more than one generation// - is sure to free memory even if there is a reachable Iteratorfor (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++;}
get(int index)
调用 node(index),执行查找 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;}}
这里判断了 index 的位置,决定是从前往后遍历,还是从后往前遍历
set(int index, E element)
public E set(int index, E element) {Node<E> x = node(index);E oldVal = x.item;x.item = element;return oldVal;}
add(int index, E element)
根据 index 的位置执行不同的逻辑
public void add(int index, E element) {checkPositionIndex(index);if (index == size)linkLast(element);elselinkBefore(element, node(index));}
linkLast 插入到末尾
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;elsel.next = newNode;size++;modCount++;}
linkBefore 先找到节点,再插入到前面
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;elsepred.next = newNode;size++;modCount++;}
remove(int index)
unlink ,node 查找逻辑上文已经分析了
public E remove(int index) {checkElementIndex(index);return unlink(node(index));}
indexOf(Object o)
就是简单的遍历记录 index 位置,找到后返回 index 值
