成员变量
//集合中数据个数
transient int size = 0;
//头结点
transient Node<E> first;
//尾节点
transient Node<E> last;
//和ArrayList一样,对集合进行增加和删除数据 ,则会修改该值
protected transient int modCount = 0;
数据被包装为Node
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;
}
}
存放数据相关方法
public boolean offer(E e) {
return add(e);
}
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public boolean offerLast(E e) {
addLast(e);
return true;
}
public boolean add(E e) {
//添加到链表尾部
linkLast(e);
return true;
}
public void addFirst(E e) {
//添加到链表头部
linkFirst(e);
}
public void addLast(E e) {
//添加到链表尾部
linkLast(e);
}
public void push(E e) {
addFirst(e);
}
void linkLast(E e) {
//获取尾节点
final Node<E> l = last;
//实例化node对象
final Node<E> newNode = new Node<>(l, e, null);
//将尾节点设置为newNode
last = newNode;
//如果尾节点null (当前链表中没有任何节点)
if (l == null)
//将头结点也设置为newNode
first = newNode;
else
//将原尾节点的下一个节点设置为newNode
l.next = newNode;
//size加一 modCount加一
size++;
modCount++;
}
private void linkFirst(E e) {
//获取头节点
final Node<E> f = first;
//实例化node对象
final Node<E> newNode = new Node<>(null, e, f);
//将头结点设置为newNode
first = newNode;
//如果头节点null (当前链表中没有任何节点)
if (f == null)
//将尾结点也设置为newNode
last = newNode;
else
//设置原头结点的上一个节点为newNode
f.prev = newNode;
//size加一 modCount加一
size++;
modCount++;
}
//添加一个集合的数据到链表中
public boolean addAll(Collection<? extends E> c) {
//从size位置开始 将集合的数据插入到链表中
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
//检查index合法性
checkPositionIndex(index);
//将集合数据获取成数组形式
Object[] a = c.toArray();
//需要存放的数据的数量
int numNew = a.length;
//返回false,没有添加任何数据
if (numNew == 0)
return false;
Node<E> pred, succ;
//index等于size,则说明从链表尾部开始插入数据
if (index == size) {
//succ置为空
succ = null;
//pred置为尾节点
pred = last;
}
//不是从链表尾部插入数据
else {
//获取到index位置的node节点,赋值给succ
succ = node(index);
//pred设置为succ的前驱节点
pred = succ.prev;
}
//遍历数组
for (Object o : a) {
//将数组的数据包装为node,前驱节点为pred
Node<E> newNode = new Node<>(pred, e, null);
//如果pred为空,则说明从链表头开始添加数据
//将头结点设置为newNode
if (pred == null)
first = newNode;
//头街点不为空,将pred的后继节点设置为newNode
else
pred.next = newNode;
//将pred赋值为newNode
pred = newNode;
}
//走到这里,新插入进来的集合的链表已经构造完成。
//succ为空,则说明是从链表尾部开始插入数据的
if (succ == null) {
//将尾节点设置为pred
last = pred;
}
//不是从链表尾部开始插入数据
else {
//将pred的后继节点设置为succ (原本index位置的node,原本index位置及以后的节点在被设置回来)
pred.next = succ;
//将succ的前驱节点设置pred
succ.prev = pred;
}
//size加上添加进来的数据的数量
size += numNew;
//modCount增加
modCount++;
return true;
}
//向指定位置添加数据
public void add(int index, E element) {
checkPositionIndex(index);
//index等于size,直接添加到链表尾部
if (index == size)
linkLast(element);
else
//先调用node方法找到链表中index位置的node
linkBefore(element, node(index));
}
void linkBefore(E e, Node<E> succ) {
//获取succ的前驱节点
final Node<E> pred = succ.prev;
//将e包装为node , 前驱节点设置为 pred 后继节点设置为succ
final Node<E> newNode = new Node<>(pred, e, succ);
//将succ前驱节点设置为newNode
succ.prev = newNode;
//如果pred 为空, 则说明succ为头结点
if (pred == null)
//将头结点设置为newNode
first = newNode;
//否则 , 将succ的前驱节点 的 后继节点设置为newNode
else
pred.next = newNode;
//size增加1
size++;
//modCount增加1
modCount++;
}
移除数据相关方法
public boolean remove(Object o) {
//移除值为null的node
if (o == null) {
//从头遍历链表
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
//从链表中移除该数据
unlink(x);
return true;
}
}
}
//移除值不为null的node
else {
for (Node<E> x = first; x != null; x = x.next) {
//调用equals方法比较node的值
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
//没有找到匹配的node去移除,则返回false
return false;
}
E unlink(Node<E> x) {
//获取被移除node的值
final E element = x.item;
//获取node的下一个节点 --- 后继节点
final Node<E> next = x.next;
//获取node的上一个节点 --- 前驱结点
final Node<E> prev = x.prev;
//调整前驱结点
//如果前驱结点为空,则说明node是头节点
if (prev == null) {
//将头结点设置为node的后继节点
first = next;
}
//node不是头结点
else {
//将node的前驱结点的后继节点 设置为 node的后继节点
prev.next = next;
//将node的前驱结点置空
x.prev = null;
}
//调整后继节点
//如果后继节点为空,则说明node是尾节点
if (next == null) {
//将尾节点置为node的前驱结点
last = prev;
}
//node不是尾节点
else {
//将node的后继节点的前驱节点 设置为 node的前驱节点
next.prev = prev;
//将node后继节点设置为空
x.next = null;
}
//将node的值设置为空
x.item = null;
//size减一 modCount加一
size--;
modCount++;
//返回被移除的node的值
return element;
}
//移除头节点,并返回被移除的节点
public E removeFirst() {
//获取头结点
final Node<E> f = first;
//头结点不能为空,否则抛异常
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
//获取node的值
final E element = f.item;
//获取node的后继节点
final Node<E> next = f.next;
//将node的值和后继节点置为空
f.item = null;
f.next = null; // help GC
//将头结点置为node的后继节点
first = next;
//如果后继节点为空,则链表中只有node这一个节点,则将尾节点置为空
if (next == null)
last = null;
//node存在后继节点
else
//将node的后继节点 的 前驱结点置为空 , 不用再指向被移除的node了
next.prev = null;
//size减一 modCount加一
size--;
modCount++;
//返回被移除的node的值
return element;
}
//移除尾节点,并返回被移除的节点
public E removeLast() {
//获取尾节点
final Node<E> l = last;
//尾结点不能为空,否则抛异常
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
private E unlinkLast(Node<E> l) {
//获取尾节点的值
final E element = l.item;
//获取node的前驱节点
final Node<E> prev = l.prev;
//将node的值和前驱节点置空
l.item = null;
l.prev = null; // help GC
//将尾节点设置为node的前驱节点
last = prev;
//如果node的前驱节点为空 , 则链表中只有node这一个节点,则将头节点置为空
if (prev == null)
first = null;
//node存在前驱节点
else
//将node的前驱节点 的 后继节点设置为空
prev.next = null;
//size减一 modCount加一
size--;
modCount++;
//返回被移除的node的值
return element;
}
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
public E pop() {
return removeFirst();
}
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
获取数据相关方法
//获取头结点
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
//获取尾节点
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
public E get(int index) {
//检查下标合法性
checkElementIndex(index);
//返回链表中index位置的node的值
return node(index).item;
}
//获取链表指定位置的node
Node<E> node(int index) {
//判断 index位置 在链表的左半部还是右半部
//index在链表的左半部
if (index < (size >> 1)) {
//从头结点开始向后遍历,找到index位置的node节点返回
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
}
//index在链表的右半部
else {
//从尾结点开始向前遍历,找到index位置的node节点返回
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E element() {
return getFirst();
}
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
clear方法
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设置赋值为后继节点
x = next;
}
//将头结点尾节点置空
first = last = null;
//size设置为0
size = 0;
//modCount增加
modCount++;
}
listIterator
public ListIterator<E> listIterator(int index) {
//index检查
checkPositionIndex(index);
//返回从index位置开始的迭代器
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
//记录当前遍历到的node
private Node<E> lastReturned;
//记录下一个node
private Node<E> next;
//记录下一个遍历的node的下标
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
//next赋值为index位置的node
next = (index == size) ? null : node(index);
//nextIndex赋值为index
nextIndex = index;
}
//nextIndex小于size,则还有数据可以遍历
public boolean hasNext() {
return nextIndex < size;
}
//向后遍历
public E next() {
//检查expectedModCount 和 modCount是否一致 ,不一致抛出异常 , (当有其他线程在修改链表,则本次ListItr是无效的)
checkForComodification();
//没有数据可以再往下遍历了
if (!hasNext())
throw new NoSuchElementException();
//lastReturned 设置为 next
lastReturned = next;
//next设置为 下一个节点
next = next.next;
//nextIndex加一
nextIndex++;
//返回遍历到的node的值
return lastReturned.item;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
//向前遍历
public E previous() {
checkForComodification();
//如果没有从从index向后遍历过节点返回 , 抛异常
if (!hasPrevious())
throw new NoSuchElementException();
//next为空,则已经遍历完全了,返回尾节点
//否则 lastReturned , next 设置为 next的上一个节点
lastReturned = next = (next == null) ? last : next.prev;
//nextIndex减一
nextIndex--;
//返回lastReturned 的值
return lastReturned.item;
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
//移除节点
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
//获取lastReturned的后继节点
Node<E> lastNext = lastReturned.next;
//从链表中移除该节点
unlink(lastReturned);
//如果next等于lastReturned (调用了一次previous,然后再调用到remove,则此时next == lastReturned)
if (next == lastReturned)
//将next设置为lastNext
next = lastNext;
else
//nextIndex减一
nextIndex--;
//lastReturned 置空
lastReturned = null;
//调用了unlink,modCount++了 这里expectedModCount也要++
expectedModCount++;
}
//设置节点的值
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
//添加节点
public void add(E e) {
checkForComodification();
//lastReturned 置为空
lastReturned = null;
//如果next为空, 则说明已经遍历到尾节点
if (next == null)
//将e添加到链表尾部
linkLast(e);
else
//将e添加到链表中next的前一个位置
linkBefore(e, next);
//nextIndex加一
nextIndex++;
//link方法使得modCount++ , 则 expectedModCount 也需要 ++
expectedModCount++;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
双向链表基础操作,完全可以照着LinkedList学下哦。