兼具List的有序性和Deque的队列的特性,这个集合平常项目中使用的比较少,接着刷题的机会了解到这个数据集合,趁机来深度学习下源码知识,希望对大家可以有所帮助
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
//集合size属性
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;
/**
*当前集合被修改的次数,类似于版本锁,当发生集合Node节点增删的时候当前值做自增
*
* The number of times this list has been structurally modified.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* fail-fast behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
*
Use of this field by subclasses is optional. If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
*/
protected transient int modCount = 0;
/**
* 静态内部类 双向链表
*/
private static class Node<E> {
//Node节点中存储的元素值
E item;
//下一个Node节点
Node<E> next;
//上一个Node节点
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}
LinkedList(Collection extends E> c)
批量添加集合内容到LinkedList的构造方法public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
LinkedList()
无参构造方法//无参构造方法,初始化集合对象,此时初始化以后的是一个空的集合size=0
public LinkedList() {
}
public Iterator<E> iterator() {
//调用List子集实现的方法
return listIterator();
}
add(E element)
在集合尾部插入元素,几乎等价于linkLast(E element)//默认在链表尾部插入数据
public boolean add(E element) {
linkLast(e);
return true;
}
addAll(Collection extends E> c)
批量添加集合元素到当前集合中public boolean addAll(Collection<? extends E> c) {
//默认将元素添加到当前集合的末尾,调用addALL方法时index参数设置为当前集合的size属性
//调用List子集实现的方法
return addAll(size, c);
}
contains(Object o)
判断集合是否包含某个元素public boolean contains(Object o) {
//调用List子集实现的方法
return indexOf(o) != -1;
}
set(int index, E element)
修改元素值,同时返回原先存储的Node节点元素值//使用无参构造方法实例化LinkedList后立即调用set(int index, E element)或者操作会抛出下标越界的异常IndexOutOfBoundsException,这时通不过checkPositionIndex方法的校验,因为Node节点first和last都还未实例化
//该方法不改变集合结构,不对修改集合长度。设置前提是当前Node节点已经存在,
public E set(int index, E element) {
//判断下标是否越界
checkElementIndex(index);
//循环遍历获取到响应的Node节点
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
add(int index, E element)
查找并且插入相应的元素值//使用无参构造方法实例化LinkedList后立即调用add(int index, E element)操作会抛出下标越界的异常IndexOutOfBoundsException,这时通不过checkPositionIndex方法的校验,因为Node节点first和last都还未实例化
public E add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
addAll(int index, Collection extends E> c)
批量添加集合元素到制定下标之后当前集合中(重载)public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
//Collection的子集都必须实现的方法toArray()
Object[] a = c.toArray();
//待添加集合的长度
int numNew = a.length;
//待添加集合为空,方法终止
if (numNew == 0)
return false;
//定义当前待插入数据的最前置Node节点pred
//和
Node<E> pred, succ;
//将目标集合的元素插入到当前集合尾部
if (index == size) {
succ = null;
//最前置节点Node当于当前集合的last,完成两个集合的头尾衔接
pred = last;
} else {
//将目标集合的元素插入到本集合中间的某个特定下标的位置
//获取当前index的Node节点,并将其赋值给succ
succ = node(index);
//替换当前下标值对应节点以及其之后的位置(连它一起往后,再此之前开始插入值),将当前Node.prev设置为待添加集合的pred节点
pred = succ.prev;
}
//循环赋值
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
//pred为空则表示原先的集合为空,直接将新建的Node设置为头节点
first = newNode;
else
//再pred的尾部插入新建的节点
pred.next = newNode;
//把新加入的节点赋值给pred,后续的新增节点可以继续通过循环往后追加值
pred = newNode;
}
if (succ == null) {
//根据传入index找不到数据,直接将循环以后最后一个待插入元素赋值给当前集合的last
last = pred;
} else {
//把待插入集合最后一个元素的next和原始集合下标为index的节点串起来,双向链表接通
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
indexOf(Object o)
获取某个元素在集合结构中的下标public int indexOf(Object o) {
int index = 0;
if (o == null) {
//待判断元素为null,从first开始通过链表往后顺序到第一个空元素并且返回下标
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
//如果待判断元素非空,从first开始通过链表往后顺序查找,挨个判断是否与其相等
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
listIterator()
获取List类型的可迭代对象public ListIterator<E> listIterator() {
return listIterator(0);
}
listIterator(final int index)
获取集合中某个下标值之后的List类型的可迭代对象 public ListIterator<E> listIterator(final int index) {
//这部分代码实现在其父类AbstractSequentialList的父类AbstractList中有做相关的实现
rangeCheckForAdd(index);
return new ListItr(index);
}
get(int index)
获取当前集合中某个下标节点存储的值public E get(int index) {
//判断下标是否越界
checkElementIndex(index);
//通过node方法遍历找到传入index对应的Node,并且获取其item值
return node(index).item;
}
remove(int index)
删除当前集合中某个下标节点存储的值public E remove(int index) {
//判断下标是否越界
checkElementIndex(index);
//通过node方法遍历找到传入index对应的Node,然后通过unlink方法删除元素值
return unlink(node(index));
}
poll()
获取并且删除集合的第一个元素//实现上和pollFirst()一模一样
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
offer(E e)
在集合尾部插入元素public boolean offer(E e) {
return add(e);
}
_
descendingIterator()
获取一个可以逆序迭代的迭代器public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
/**
* Adapter to provide descending iterators via ListItr.previous
*/
private class DescendingIterator implements Iterator<E> {
private final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}
addFirst(E element)
在集合头部插入元素public void addFirst(E e) {
linkFirst(e);
}
addLast(E element)
在集合尾部插入元素public void addLast(E e) {
linkLast(e);
}
pollFirst()
获取并且删除集合的第一个元素public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
pollLast()
获取并且删除集合的最后一个元素public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
peekFirst()
获取集合的第一个元素public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
peekLast()
获取集合的最后一个元素public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
offerFirst(E e)
在集合头部插入元素public boolean offerFirst(E e) {
addFirst(e);
return true;
}
offerLast(E e)
在集合尾部插入元素public boolean offerLast(E e) {
addLast(e);
return true;
}
checkPositionIndex(int index)
确认当前传入的下标是否为可迭代的,否则抛出异常private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
isPositionIndex(int index)
判断当前传入的下标是否为可迭代的判断当前传入的下表是否为可迭代的, 可选范围是0<= index <= size 在链表的迭代器(Iterator)里,双向Queue(Deque)中可以正向、反向的迭代,所以index的可选范围对比数组是要大一点
/**
* Tells if the argument is the index of a valid position for an
* iterator or an add operation.
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
checkElementIndex(int index)
确认当前传入的下标是否为越界,否则抛出异常private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
isElementIndex(int index)
判断当前传入的下标是否为越界/**
* Tells if the argument is the index of an existing element.
* 判断传入的下标是否存在相应的元素, 可选范围是0<= index < size 对应数组下标从0到size -1
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
node(int index)
根据下标来迭代获取响应的元素/**
* 循环迭代获取响应index的元素
*/
Node<E> node(int index) {
//这一步判断目前都
// assert isElementIndex(index);
//size >> 1 在未超出数据类型限制的情况下,右移1尾效果等价于/2
//因为LinkedList实现的是Deque(双向队列)
// 因此如果 index < size/2 时考虑从头fisrt开始正序遍历
// 因此如果 index >= size/2 时考虑从头last开始反序遍历
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;
}
}
linkFirst(E element)
在集合头部插入元素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++;
}
linkLast(E 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++;
}
linkBefore(E e, Node succ)
在集合某个Node节点之前插入元素void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//待插入集合的头指向相应Node节点
final Node<E> pred = succ.prev;
//创建待插入节点
final Node<E> newNode = new Node<>(pred, e, succ);
//相应节点succ的双向链补全指向待插入节点
succ.prev = newNode;
if (pred == null)
//如果相应节点为空,则将待插入元素设置成集合的头节点,如果原先集合有内容,这一顿操作就会造成链表断裂
first = newNode;
else
//双向链表闭环,将当前节点succ的前置节点的next设置为新插入的节点
pred.next = newNode;
size++;
modCount++;
}
unlinkFirst(E element)
删除集合头结点//该方法仅有两处被调用的地方,分别是pollFirst()和poll(),都是需要拿到集合的头节点并且删除头节点的操作
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
//获取当前待删除Node存储的数据值,用于完成方法后返回
final E element = f.item;
//获取到当前待删除Node的下一个节点,用于替换当前节点
final Node<E> next = f.next;
//清理当前Node的相关信息,等待GC回收
f.item = null;
f.next = null; // help GC
//将当前待删除Node的下一个节点赋值给集合的first节点
first = next;
if (next == null)
//nextNode为空标志当前集合为空,上面删除的是集合中的唯一元素
last = null;
else
//集合不为空时,将集合的头节点的prev斩断,如果不执行这一步,头节点的prev还是指向待删除的但是内容已经清空的这个节点
//个人觉得这里的代码写成first.prev=null可读性会更好
next.prev = null;
size--;
modCount++;
return element;
}
unlinkLast(Node l)
删除集合尾节点//代码逻辑和unlinkFirst类似,只是需要逆向处理
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
unlink(Node x)
在集合中某个Node节点的值//简单的说就是剪短旧链 让x.pref.next=x.next x.next.pref=x.pref
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;
}