容器(三)LinkedList源码解析
-
定义:实现了List和Deque接口,既可以看作是一个顺序容器,又可以看作一个队列。所以在需要栈和队列的场景下使用它,但是ArrayDeque更适合栈和队列。
-
组成部分
//长度 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; //内部类-节点 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; } }
-
重要方法
List接口方法
删除:
remove(index),remove(e)
删除指定位置元素、删除与指定元素匹配的首个位置元素//因为null也是元素,考虑一下情况 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; } //删除元素原理 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; //被删元素前驱为null x.prev = null; } //后继为空,即为尾结点 if (next == null) {// 最后一个元素 last = prev;//前驱成为尾结点 } else { //存在后继,后继节点前驱更替 next.prev = prev; //被删节点后继为null x.next = null; } //元素为空,准备GC x.item = null; // GC size--; modCount++; return element; }
add(e),add(index,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++;
modCount++;
}
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
//e 新增元素 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++;
}
Queue接口的方法
/**
* 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);
}
Qeque方法
/**
* 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;
}