1、add(E e) 添加方法,会直接在LinkedList 的尾部插入元素,方法内部调用的linkLast(e);
void linkLast(E e) {
final Node l = last;
final Node newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
首先将成员变量last赋值给临时变量l,然后使用有参构造创建新的节点newNode,并指定新节点的直接前驱为l,元素为e,直接后继为null
将新创建的newNode赋给last变量,然后判断l是否为null,为空则表示当前链表没有元素,那么添加后链表的第一个元素也是newNode,first = newNode;
否则将l的后继指向nowNode,l.next = newNode; 。
2、add(int index, E element) 在指定位置插入节点
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
经过下标越界检查后,首先判断要插入的位置是否为链表的末尾,if (index == size),如果是,就调用linkLast方法完成添加数据;
否则,调用linkBefore方法添加
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++;
}
succ变量是通过node方法在集合中查找的,该方法是返回指定下标的非空节点,进入linkBefore方法内
首先将succ的直接前驱的引用指向临时变量pred,然后通过有参构造创建新的节点newNode,并指定新节点的直接前驱为pred,直接后继为指定位置所在的succ
修改succ的前驱为newNode,succ.prev = newNode;
判断pred是否为空,if (pred == null),是 则表示指定的位置节点succ是首节点,将首节点first修改为newNode,first = newNode;
不为空,则将当前位置节点succ的前驱pred的直接后继指向新节点newNode,pred.next = newNode; 。
3、removeFirst()、removeLast() 方法
两个方法,都会先判断fist或last变量是否为null,如果是,会抛出throw new NoSuchElementException();
removeFirst方法是内部调用unlinkFirst(Node<E> f)方法,首先获取到first节点的元素final E element = f.item 以及 下一个节点 final Node<E> next = f.next;
将这两个变量设置为null,f.item = null; f.next = null; ,然后将刚刚已经获取到的当前节点的下一个节点next赋值给first变量,first = next;
然后判断next变量是否为空 if (next == null) last = null; ,为空则表示当前链表只有一个元素,将last也设置为null,否,则将next的直接前驱设置为null,next.prev = null;。
removeLast方法,内部调用的是unlinkLast(Node<E> l),先获取节点元素和直接前驱 final E element = l.item;final Node<E> prev = l.prev;
设置这两个变量为null,l.item = null;l.prev = null; // help GC
将变量last修改为prev,即最后一个节点的上一个node,last = prev;
然后判断prev是否为空,是,则表示当前链表只有一个元素,将first也设置为null,否,则prev的直接后继next设置为null。
4、remove(E e)删除指定元素、remove(int index)删除指定索引处的元素
都是通过调用unlink(Node<E> x)方法完成的:
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;
}
方法首先获取当前节点的元素以及直接后继节点next和直接前驱节点prev,
首先判断prev是否为空,是,则表示当前节点是头节点,那么将首节点first设置为下一个节点next,first = next;,否,则将x节点的上一个节点的直接后继设置为x的下一个节点next,prev.next = next;,并断开x与prev的链接,x.prev = null;。
然后判断next是否为空,是表示当前节点是尾节点,将尾节点设置为当前x节点的前一个节点prev, last = prev;,否,则将x节点的下一个节点next的直接前驱设置为x的直接前驱prev,next.prev = prev;,并断开x和next的链接,x.next = null;。
到此,x已经断开了与直接前驱和直接后继的链接,往下再将x的元素设置为null,x.item = null;,即完成节点删除。