LinkedList是双向链表结构,链表数据结构的特点是每个元素分配的空间不必连续、插入和删除元素时速度非常快、但访问元素的速度较慢。
LinkedList继承了AbstractSequentialList
public class LinkedList extends AbstractSequentialList implements List, Deque, Cloneable, Serializable
LinkedList的全局变量有size、first和last。size用于记录当前链表的长度,first用于记录链表头部第一个节点元素的信息,last用于记录链表尾部最后一个节点元素的信息
transient int size;
transient LinkedList.Node first;
transient LinkedList.Node last;
我们再来看看头节点LinkedList.Node内部私有类,这个Node内部私有类存储着一个节点的关键信息,item代表当前节点元素,next代表当前节点元素的下一个节点元素,prev代表当前节点元素的上一个节点元素。
private static class Node {
//当前节点的元素
E item;
//下一个节点的元素
LinkedList.Node next;
//上一个节点的元素
LinkedList.Node prev;
//Node的构造方法
Node(LinkedList.Node var1, E var2, LinkedList.Node var3) {
this.item = var2;
this.next = var3;
this.prev = var1;
}
}
获取LinkedList头节点元素
public E getFirst() {
//将全局变量头节点first赋值给var1
LinkedList.Node var1 = this.first;
//若var1为null,抛错
if (var1 == null) {
throw new NoSuchElementException();
}
//否则返回var1的item
else {
return var1.item;
}
}
element方法内部调用getFirst方法
public E element() {
return this.getFirst();
}
peek方法是获取LinkedList头节点的方法,getFirst和element也是用来获取头节点的,但是getFirst和element如果找不到头节点会抛错,peek找不到头节点则返回null
public E peek() {
//var1赋值为头节点
LinkedList.Node var1 = this.first;
//如果头节点为null则返回null,不为null返回item
return var1 == null ? null : var1.item;
}
获取LinkedList尾节点元素
public E getLast() {
//将全局变量尾节点last赋值给var1
LinkedList.Node var1 = this.last;
//如果尾节点为null,抛错
if (var1 == null) {
throw new NoSuchElementException();
}
//返回var1的item
else {
return var1.item;
}
}
根据下标获取LinkedList对应下标的元素
public E get(int var1) {
this.checkElementIndex(var1);
return this.node(var1).item;
}
//检查元素下标位置是否合法
private void checkElementIndex(int var1) {
//若传入的元素下标超出了本LinkedList的有效范围,抛错
if (!this.isElementIndex(var1)) {
throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));
}
}
//检查传入的下标是否合法
private boolean isElementIndex(int var1) {
//若下标大于等于0且小于LinkedList的size,返回true
return var1 >= 0 && var1 < this.size;
}
//根据下标获取LinkedList中指定下标的元素node
LinkedList.Node node(int var1) {
LinkedList.Node var2;
int var3;
if (var1 < this.size >> 1) {
var2 = this.first;
for(var3 = 0; var3 < var1; ++var3) {
var2 = var2.next;
}
return var2;
} else {
var2 = this.last;
for(var3 = this.size - 1; var3 > var1; --var3) {
var2 = var2.prev;
}
return var2;
}
}
移除首节点元素first
public E removeFirst() {
//将LinkedList首节点元素赋值给
LinkedList.Node var1 = this.first;
//若var1为null,抛错
if (var1 == null) {
throw new NoSuchElementException();
}
//否则开始移除首节点
else {
return this.unlinkFirst(var1);
}
}
//移除首节点
private E unlinkFirst(LinkedList.Node var1) {
//将首节点var1的当前元素item赋值给var2
Object var2 = var1.item;
//用var3存储首节点var1的下一个节点元素
LinkedList.Node var3 = var1.next;
//将首节点的当前元素item赋值为null
var1.item = null;
//将首节点的下一个节点元素next赋值为null
var1.next = null;
//将首节点赋值为var3
this.first = var3;
//若var3为null,则给尾节点赋值为null
if (var3 == null) {
this.last = null;
}
//这里var1作为首节点已经被移除了,所以var1的下一节点var3的前一节应该赋值为null
else {
var3.prev = null;
}
//size减一
--this.size;
++this.modCount;
//返回被移除的元素
return var2;
}
移除尾节点元素last
public E removeLast() {
//将LinkedList的尾节点赋值给var1
LinkedList.Node var1 = this.last;
//若尾节点为null,抛错
if (var1 == null) {
throw new NoSuchElementException();
}
//不为null则移除尾节点
else {
return this.unlinkLast(var1);
}
}
private E unlinkLast(LinkedList.Node var1) {
//将尾节点var1的当前元素赋值给var2
Object var2 = var1.item;
//将尾节点的前一节点赋值给var3
LinkedList.Node var3 = var1.prev;
//将尾节点var1的item赋值为null
var1.item = null;
//将尾节点var1的上一节点元素赋值为null
var1.prev = null;
//将尾节点赋值为var3
this.last = var3;
//如果前一节点为null
if (var3 == null) {
//将首节点赋值为null
this.first = null;
} else {
//将前一节点var3的下一节点赋值为null
var3.next = null;
}
//size-1
--this.size;
++this.modCount;
//返回被移除的var2元素
return var2;
}
添加首节点
public void addFirst(E var1) {
this.linkFirst(var1);
}
private void linkFirst(E var1) {
//用var2来存储当前的首节点
LinkedList.Node var2 = this.first;
//新建var3首节点元素,其前节点为null(这里因为首节点的前一节点肯定为null),后节点为var2,当前节点为传入的var1
LinkedList.Node var3 = new LinkedList.Node((LinkedList.Node)null, var1, var2);
//将新建的var3首节点元素赋值给this.first
this.first = var3;
//如果之前的首节点为null,那么新建的var3元素既是首节点也是尾节点
if (var2 == null) {
//将LinkedList尾节点赋值为var3
this.last = var3;
} else {
//var2不为null的话,则var3就是var2的前一节点
var2.prev = var3;
}
//size+1
++this.size;
++this.modCount;
}
addLast方法,将新元素节点增加到链表最后作为链表的尾节点
public void addLast(E var1) {
this.linkLast(var1);
}
void linkLast(E var1) {
//将尾节点赋值给var2
LinkedList.Node var2 = this.last;
//新建一个以var1为item的node节点对象var3
LinkedList.Node var3 = new LinkedList.Node(var2, var1, (LinkedList.Node)null);
//将新建的var3节点赋值给尾节点last
this.last = var3;
if (var2 == null) {
//若原来的尾节点var2为null,则代表这个LinkedList一开始就没有节点,所以新建的尾节点也就是头节点
this.first = var3;
} else {
//否则var2的下一节点就是var3
var2.next = var3;
}
//容量+1
++this.size;
++this.modCount;
}
contains方法通过调用indexOf方法判断元素所在位置下标是否为-1来判断元素是否存在
public boolean contains(Object var1) {
return this.indexOf(var1) != -1;
}
public int indexOf(Object var1) {
int var2 = 0;
LinkedList.Node var3;
//若传入的元素var1为null
if (var1 == null) {
//以首节点开始,只要下一节点不为null,就一直循环
for(var3 = this.first; var3 != null; var3 = var3.next) {
//如果当前节点为null,返回其下标var2
if (var3.item == null) {
return var2;
}
//下标+1
++var2;
}
}
//若传入的var1不为null
else {
//以首节点开始,只要下一节点不为null,就一直循环
for(var3 = this.first; var3 != null; var3 = var3.next) {
//比对var1和var3,找到后直接返回其下标
if (var1.equals(var3.item)) {
return var2;
}
//下标+1
++var2;
}
}
return -1;
}
返回LinkList的长度
public int size() {
return this.size;
}
这里的add方法和上面的addLast实现原理是一样的,只不过多返回了一个true
public boolean add(E var1) {
this.linkLast(var1);
return true;
}
void linkLast(E var1) {
//将尾节点赋值给var2
LinkedList.Node var2 = this.last;
//新建一个以var1为item的node节点对象var3
LinkedList.Node var3 = new LinkedList.Node(var2, var1, (LinkedList.Node)null);
//将新建的var3节点赋值给尾节点last
this.last = var3;
if (var2 == null) {
//若原来的尾节点var2为null,则代表这个LinkedList一开始就没有节点,所以新建的尾节点也就是头节点
this.first = var3;
} else {
//否则var2的下一节点就是var3
var2.next = var3;
}
//容量+1
++this.size;
++this.modCount;
}
在指定下标设置添加元素
public void add(int var1, E var2) {
//检查下标位置是否合法
this.checkPositionIndex(var1);
//如果传入var1等于当前容量大小
if (var1 == this.size) {
//则直接将传入的元素存入链表的最后
this.linkLast(var2);
} else {
//否则就往前面加
this.linkBefore(var2, this.node(var1));
}
}
void linkLast(E var1) {
//将尾节点赋值给var2
LinkedList.Node var2 = this.last;
//新建一个以var1为item的node节点对象var3
LinkedList.Node var3 = new LinkedList.Node(var2, var1, (LinkedList.Node)null);
//将新建的var3节点赋值给尾节点last
this.last = var3;
if (var2 == null) {
//若原来的尾节点var2为null,则代表这个LinkedList一开始就没有节点,所以新建的尾节点也就是头节点
this.first = var3;
} else {
//否则var2的下一节点就是var3
var2.next = var3;
}
//容量+1
++this.size;
++this.modCount;
}
void linkBefore(E var1, LinkedList.Node var2) {
//用var3暂存原节点的前一节点
LinkedList.Node var3 = var2.prev;
//新建var4节点对象,用var1作为item,var3作为前一节点,var2作为后一节点
LinkedList.Node var4 = new LinkedList.Node(var3, var1, var2);
//将var2的前一节点赋值为新对象var4
var2.prev = var4;
//如果var3为Null,
if (var3 == null) {
//则var4就是头节点
this.first = var4;
} else {
//否则给var3的下一节点赋值为var4
var3.next = var4;
}
//容量+1
++this.size;
++this.modCount;
}
在指定下标位置设置元素
public E set(int var1, E var2) {
//先检查下标是否合法
this.checkElementIndex(var1);
//根据传入的下标查询对应的节点元素
LinkedList.Node var3 = this.node(var1);
//用var4暂存查到的原节点元素的item
Object var4 = var3.item;
//将var1下标对应的元素item替换成传入的元素
var3.item = var2;
//最后返回被替换的元素
return var4;
}
//检查元素下标位置是否合法
private void checkElementIndex(int var1) {
//若传入的元素下标超出了本LinkedList的有效范围,抛错
if (!this.isElementIndex(var1)) {
throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));
}
}
//检查传入的下标是否合法
private boolean isElementIndex(int var1) {
//若下标大于等于0且小于LinkedList的size,返回true
return var1 >= 0 && var1 < this.size;
}
//根据下标获取LinkedList中指定下标的元素node
LinkedList.Node node(int var1) {
LinkedList.Node var2;
int var3;
if (var1 < this.size >> 1) {
var2 = this.first;
for(var3 = 0; var3 < var1; ++var3) {
var2 = var2.next;
}
return var2;
} else {
var2 = this.last;
for(var3 = this.size - 1; var3 > var1; --var3) {
var2 = var2.prev;
}
return var2;
}
}
public boolean remove(Object var1) {
LinkedList.Node var2;
//如果传入的var1为null
if (var1 == null) {
//以头节点开始,只要下一节点不为Null,就一直循环
for(var2 = this.first; var2 != null; var2 = var2.next) {
//找到item为null的节点后开始移除这个节点
if (var2.item == null) {
this.unlink(var2);
return true;
}
}
}
//如果传入的var1不为null
else {
//以头节点开始,只要下一节点不为Null,就一直循环
for(var2 = this.first; var2 != null; var2 = var2.next) {
//直到找到var1对应的节点,开始移除
if (var1.equals(var2.item)) {
this.unlink(var2);
return true;
}
}
}
return false;
}
//解除链接的方法
E unlink(LinkedList.Node var1) {
//用var2暂存要被移除的节点var1.item
Object var2 = var1.item;
//用var3存储var1的下一节点
LinkedList.Node var3 = var1.next;
//用var4存储var1的上一节点
LinkedList.Node var4 = var1.prev;
//如果var4为null,又因为var1要被移除,所以本LinkedList的首节点直接赋值为var3
if (var4 == null) {
this.first = var3;
}
//否则var4的下一节点赋值为var3,var1的上一节点赋值为null
else {
var4.next = var3;
var1.prev = null;
}
//如果var3为null,又因为var1要被移除,所以var4既是首节点也是尾节点
if (var3 == null) {
this.last = var4;
}
//如果var3不为Null,则var3的前一个节点是var4,var1的下一节点为null
else {
var3.prev = var4;
var1.next = null;
}
//var1的item赋值为null
var1.item = null;
//size-1
--this.size;
++this.modCount;
//返回被移除的节点var2
return var2;
}
remove重载方法,内部调用removeFirst方法,移除头节点
public E remove() {
return this.removeFirst();
}
poll方法内部调用unlinkFirst方法来移除头节点,remove和removeFirst找不到头节点时会抛错,而poll找不到头节点只会返回null
public E poll() {
LinkedList.Node var1 = this.first;
return var1 == null ? null : this.unlinkFirst(var1);
}
研读源码的时候发现里面的变量大多是var1,var2,var3,不便于理解,我自己修改了下变量名
public boolean addAll(Collection extends E> collection) {
//内部调用addAll重载方法
return this.addAll(this.size, collection);
}
//变量名太low,TODO
public boolean addAll(int size, Collection extends E> collection) {
//检查size是否在规定范围之内
this.checkPositionIndex(size);
//将Collection类型collection转化为Array类型
Object[] tempArr = collection.toArray();
//用tempArrLen存储tempArr 的长度
int tempArrLen= tempArr.length;
//如果长度为0,直接返回false
if (tempArrLen == 0) {
return false;
}
else {
LinkedList.Node var5;
LinkedList.Node var6;
//
if (size == this.size) {
var6 = null;
var5 = this.last;
} else {
var6 = this.node(size);
var5 = var6.prev;
}
Object[] var7 = tempArr;
int var8 = var3.length;
for(int i = 0; i < var8; ++i) {
Object var10 = var7[i];
LinkedList.Node var12 = new LinkedList.Node(var5, var10, (LinkedList.Node)null);
if (var5 == null) {
this.first = var12;
} else {
var5.next = var12;
}
var5 = var12;
}
if (var6 == null) {
this.last = var5;
} else {
var5.next = var6;
var6.prev = var5;
}
this.size += tempArrLen;
++this.modCount;
return true;
}
}
//检查下标是否在规定范围之内
private void checkPositionIndex(int size) {
//如果size不在范围之内,抛错
if (!this.isPositionIndex(size)) {
throw new IndexOutOfBoundsException(this.outOfBoundsMsg(size));
}
}
//判断位置下标是否在范围之内
private boolean isPositionIndex(int size) {
return size>= 0 && size <= this.size;
}
LinkedList.Node node(int var1) {
LinkedList.Node var2;
int var3;
if (var1 < this.size >> 1) {
var2 = this.first;
for(var3 = 0; var3 < var1; ++var3) {
var2 = var2.next;
}
return var2;
} else {
var2 = this.last;
for(var3 = this.size - 1; var3 > var1; --var3) {
var2 = var2.prev;
}
return var2;
}
}
LinkedList清空方法
public void clear() {
//新建临时变量var
LinkedList.Node var2;
//从LinkedList的头节点开始循环,逐个将所有节点的item、next、prev属性赋值为null
for(LinkedList.Node var1 = this.first; var1 != null; var1 = var2) {
var2 = var1.next;
var1.item = null;
var1.next = null;
var1.prev = null;
}
//再将LinkedList的头节点和尾节点赋值为null
this.first = this.last = null;
//size设置为0
this.size = 0;
++this.modCount;
}