继承结构
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
写在前面的一些方法
private void linkFirst(E 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) // 如果之前的头节点为null,说明之前整条链都是null的
last = newNode;// 现在的链表元素就一个,所以last=first
else
f.prev = newNode;// 不为null,则把第二节点链接到第一节点
size++;
modCount++;
}
-
void linkLast(E e)
与linkFirst(···)
同理
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++;
}
-
void linkBefore(E e, Node<E> succ)
在目标节点之前插入元素到链表
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;// 获取目标节点的前一个节点
// 创建一个新的节点,prev=目标节点的前一个节点,next=目标节点
// 此时新节点和前一个节点是单链,和后一个节点也是单链
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode; // 目标节点关联当前节点,形成双链
if (pred == null) // 说明目标节点是头节点
first = newNode;// 重新赋值头节点
else // 目标节点不是头节点
pred.next = newNode; // 前一个节点关联当前节点,形成双链
size++;
modCount++;
}
-
private E unlinkFirst(Node<E> 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) // 为null说明链表只有一个元素
last = null;
else
next.prev = null; // 断链
size--;
modCount++;
return element;
}
-
private E unlinkLast(Node<E> 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;
}
-
E 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) { // 为null,说明目标节点为头节点
first = next; // 重新赋值头节点 = 目标节点的下一个节点
} else {
prev.next = next; // 链接目标的前后节点
x.prev = null;// 断链
}
if (next == null) {// 为null,说明目标节点为尾节点
last = prev; // // 重新赋值尾节点 = 目标节点的上一个节点
} else {
next.prev = prev; // 链接目标的前后节点 ,形成双链
x.next = null;//断链
}
x.item = null;
size--;
modCount++;
return element;
}
Node<E> node(int index) {
// assert isElementIndex(index);
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;
}
}
一、增
public void addFirst(E e)
public void addFirst(E e) {
// 添加元素并链到头节点
linkFirst(e);
}
public void addLast(E e) {
// 添加元素并链到尾节点
linkLast(e);
}
-
public void add(E e)
<=>public void addLast(E e)
public boolean add(E e) {
linkLast(e);
return true;
}
public void add(int index, E element)
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
public boolean offer(E e)
public boolean offer(E e) {
return add(e);
}
public boolean offerFirst(E e)
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public void push(E e) {
addFirst(e);
}
-
public boolean addAll(int index, Collection<? extends E> c)
在index节点之前添加
/**
* @param index index的取值为[0,size]
* 其中[0-size) 会将集合添加到index之前的位置 eg:[1,2,3].addAll(1,[4,5,6])=[1,4,5,6,2,3]
* 为size 将集合添加到原集合队尾 eg:[1,2,3].addAll(size,[4,5,6])=[1,2,3,4,5,6]
*/
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length; // 记录入参数组的大小
if (numNew == 0) // 长度为0,结束
return false;
// pred相当于索引
Node<E> pred, succ;
// 如果index为目标队列的长度
if (index == size) {
// succ:为null节点
// pred:为队尾节点
succ = null;
pred = last;
} else {
// 可以理解为在index位置将原链“拆分”为2条链
// succ:index位置的节点
// pred:index位置节点的上一个节点
succ = node(index);
pred = succ.prev;
}
// 遍历入参数组
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
// 新建一个节点
// index in [0,size),上链为index位置节点的上一个节点,即pred
// index = size,上链为队尾last节点,即pred
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null) // index位置为头节点的情况
first = newNode; // 重新赋值头节点
else
pred.next = newNode; // 新建节点和pred节点形成双链
pred = newNode; // 把pred指向新建的这个节点,执行下一次循环
}
// 到此,pred节点为入参集合的最后一个元素的节点
if (succ == null) { // 说明index为size的情况
last = pred; // 重新赋值队尾节点
} else {
// 重新双链之前在index位置"拆分"出来的2条链,形成一整条链
pred.next = succ;
succ.prev = pred;
}
size += numNew;// 更新当前链表长度
modCount++;
return true;
}
public boolean addAll(Collection<? extends E> c)
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c); // 从队尾添加
}
二、删
-
public E removeFirst()
返回值为移除的节点的元素值
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
-
public E remove()
返回值为移除的节点的元素值
public E remove() {
return removeFirst();
}
-
public E removeLast()
,返回值为移除的节点的元素值
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
-
public boolean remove(Object o)
移除元素位置上的节点,返回值为是否查到当前元素的节点,一次只会移除一个节点
public boolean remove(Object o) {
if (o == 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;
}
-
public E remove(int index)
,返回值为移除的节点的元素值
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
-
public E pollFirst()
返回值为移除的节点的元素值
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
-
public E pollLast()
返回值为移除的节点的元素值
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
-
public E pop()
返回值为移除的节点的元素值
public E pop() {
return removeFirst();
}
三、改
-
public E set(int index, E element)
,返回值为index节点修改之前的元素
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
public void clear() {
// Clearing all of the links between nodes is "unnecessary", but:
// - helps a generational GC if the discarded nodes inhabit
// more than one generation
// - is sure to free memory even if there is a reachable Iterator
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
四、查
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
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 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;
}
public int indexOf(Object o)
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 boolean contains(Object o)
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public E element() {
return getFirst();
}
网友评论