LinkedList
细节:
-
实现方式: 双端链表,可以模拟队列和栈行为
-
允许元素为Null
-
列表中的操作将从列表的开头或结尾开始遍历,接近指定索引
-
非线程安全,如果多个线程并发访问,最新的线程修改了线程的结构,必须使用客户端加锁的方式进行同步(结构修改是添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改)
-
当创建完迭代器之后,使用了Iterator以外的操作(add | remove)对结构进行了修改,会抛出ConcurrentModificationException
成员变量:
transient Node<E> first; //头节点
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;
}
}
方法:
- 将元素E设置为链表的第一个元素
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;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
- 将元素E添加至链表末端,该方法等同于add(E e),也是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)
//这是一个元素为null的链表,设置新节点
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
- 在非空节点succ之前,插入节点e
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++;
}
- 移除头节点 , 移除尾节点同理
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;
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;
}
-
删除节点
public boolean remove(Object o) { if (o == null) { //如果要删除的元素是Null,遍历找到链表中元素为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; //如果unlink的是头节点 if (prev == null) { first = next; } else { // A => B => C 等价于 A => C 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;
}
-
返回指定元素的下标
//正序遍历 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; } //倒序遍历 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; }
队列行为:
- 查看首个元素,不会移除首个元素,如果队列是空的就返回null
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
- 将首个元素从队列中弹出,如果队列是空的,就返回null
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);// unlinkFirst 移除了该元素
}
-
查看首个元素,不会移除首个元素,如果队列是空的就抛出异常NoSuchElementException
public E element() { return getFirst(); }
栈行为:
-
将元素压入此列表表示的堆栈
public void push(E e) { addFirst(e); } -
从此列表表示的堆栈中弹出一个元素。 换句话说,删除并返回此列表的第一个元素。如果堆栈为空则抛出NoSuchElementException
public E pop() { return removeFirst(); }
拷贝:
public Object clone() {
LinkedList<E> clone = superClone();
// 设置克隆对象的“状态”
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// 浅拷贝只会拷贝对象,不会克隆里面的元素,所以遍历元素到克隆对象
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
//
private LinkedList<E> superClone() {
try {
return (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}