下面所有的方法都是将LinkedList底层数据结构看成是一个双端队列进行操作,双端队列只能对头部和末尾节点进行操作,不能对中间的节点操作。
1.获取头节点中的元素,peek方法和getFirst方法相似,getFirst方法如果头节点不存在则会抛出异常,peek方法则会返回一个null
public E peek() {
//头节点
final Node f = first;
//如果头节点为null则返回null,反之则返回头节点中的元素
return (f == null) ? null : f.item;
}
2.获取头节点中的元素(element调用的是集合中的getFirst方法)
public E element() {
return getFirst();
}
//获取头节点中的元素
public E getFirst() {
//头节点
final Node f = first;
if (f == null)
throw new NoSuchElementException();
//返回头节点中的元素
return f.item;
}
3.获取头节点中的元素并将头节点移除
public E poll() {
//头节点
final Node f = first;
//头节点为null则返回null
//不为null则返回头节点中的元素并将头节点移除
return (f == null) ? null : unlinkFirst(f);
}
//移除头节点并返回头节点中的元素并修改头节点关联的指针
private E unlinkFirst(Node f) {
// assert f == first && f != null;
//头节点中的元素
final E element = f.item;
//获取头节点next指针指向的下一个节点
final Node next = f.next;
//将头节点中的元素置为null
f.item = null;
//将头节点next指针置为null
f.next = null;
//将被删除的头节点中next指针指向的下一个节点置为新的头节点
first = next;
if (next == null)
//如果被删除的头节点中next指针指向的下一个节点为null
//则说明该双向链表中将头节点删除之后则没有别的节点
//将尾节点置为null
last = null;
else
//如果被删除的头节点中next指针指向的下一个节点不为null
//则将该节点的prev指针置为null
next.prev = null;
//更新双向链表的长度和修改次数
size–;
modCount++;
//返回被删除的元素
return element;
}
4.将指定元素添加到双向链表末尾(offse方法调用的是集合中的add方法,offerLast调用的是集合中的addLast方法)
//添加指定元素到末尾
public boolean offer(E e) {
return add(e);
}
public boolean add(E e) {
//添加元素
linkLast(e);
return true;
}
//添加指定元素到末尾
public boolean offerLast(E e) {
addLast(e);
return true;
}
public void addLast(E e) {
linkLast(e);
}
//将指定元素添加到双向链表尾节点
void linkLast(E e) {
//原尾节点
final Node l = last;
//创建新的节点将指定元素放置节点中并将节点中的上一个节点指针指向原尾节点
final Node newNode = new Node<>(l, e, null);
//将当前指定元素所在的节点设置为新的尾节点
last = newNode;
if (l == null)
//原尾节点为null则说明双向链表中没有节点元素
//将当前指定元素所在的节点设置为新的头节点
first = newNode;
else
//将原尾节点中的下一个节点指针指向新的尾节点
l.next = newNode;
size++;
modCount++;
}
5.将指定元素添加到双向链表头部(offerFirst方法调用的是集合中的addFirs方法t)
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public void addFirst(E e) {
linkFirst(e);
}
//将元素添加到双向链表头部
private void linkFirst(E e) {
//原头节点
final Node f = first;
//创建新的节点将指定元素放置节点中并将节点中的下一个节点指针指向原头节点
final Node newNode = new Node<>(null, e, f);
//将当前指定元素所在的节点设置为新的头节点
first = newNode;
if (f == null)
//原头节点为null则说明双向链表中没有节点元素
//将当前指定元素所在的节点设置为新的尾节点
last = newNode;
else
//将原头节点中的上一个节点指针指向新的头节点
f.prev = newNode;
//双向链表长度加1
size++;
//双向链表修改次数加1
modCount++;
}
6.获取头节点和尾节点中的元素(peekFirst方法与集合中的peek方法相同)
//获取头节点中的元素
public E peekFirst() {
final Node f = first;
return (f == null) ? null : f.item;
}
//获取尾节点中的元素
public E peekLast() {
final Node l = last;
return (l == null) ? null : l.item;
}
7.获取头节点和尾节点的元素并将节点移除
//获取头节点中的元素并将该头节点移除
public E pollFirst() {
final Node f = first;
return (f == null) ? null : unlinkFirst(f);
}
//获取尾节点中的元素并将该尾节点移除
public E pollLast() {
final Node l = last;
return (l == null) ? null : unlinkLast(l);
}
//移除头节点并修改该节点关联的指针
private E unlinkFirst(Node f) {
// assert f == first && f != null;
//头节点中的元素
final E element = f.item;
//获取头节点next指针指向的下一个节点
final Node next = f.next;
//将头节点中的元素置为null
f.item = null;
//将头节点next指针置为null
f.next = null;
//将被删除的头节点中next指针指向的下一个节点置为新的头节点
first = next;
if (next == null)
//如果被删除的头节点中next指针指向的下一个节点为null
//则说明该双向链表中将头节点删除之后则没有别的节点
//将尾节点置为null
last = null;
else
//如果被删除的头节点中next指针指向的下一个节点不为null
//则将该节点的prev指针置为null
next.prev = null;
//更新双向链表的长度和修改次数
size–;
modCount++;
//返回被删除的元素
return element;
}
//移除尾节点并修改该节点关联的指针
private E unlinkLast(Node l) {
// assert l == last && l != null;
final E element = l.item;
final Node prev = l.prev;
l.item = null;
l.prev = null;
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size–;
modCount++;
return element;
}
8.将指定元素添加到头部节点(push方法调用addFirst方法,而addFist方法最终调用的是linkFirst方法,可以查看序号5中的代码)
public void push(E e) {
addFirst(e);
}
9.删除头节点(pop方法调用removeFirst方法,而removeFirst方法最终调用的是unlinkFirst方法,可以查看序号7中的代码)
public E pop() {
return removeFirst();
}
10.从头节点开始查找指定元素第一个匹配到的元素的节点并删除
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
//删除指定元素
public boolean remove(Object o) {
if (o == null) {
//元素为null
//从头节点开始遍历
for (Node x = first; x != null; x = x.next) {
//如果被遍历到的节点中的元素与待删除的元素不相同
//则将被遍历到的节点中的next指针指向的节点设置为下次待遍历的节点
if (x.item == null) {
//与指定的元素匹配
//删除该元素匹配的节点并且删除相关联的指针
unlink(x);
return true;
}
}
} else {
//元素不为null
//从头节点开始遍历
for (Node x = first; x != null; x = x.next) {
//如果被遍历到的节点中的元素与待删除的元素不相同
//则将被遍历到的节点中的next指针指向的节点设置为下次待遍历的节点
if (o.equals(x.item)) {
//与指定的元素匹配
//删除该元素匹配的节点并且删除相关联的指针
unlink(x);
return true;
}
}
}
return false;
}
E unlink(Node x) {
// assert x != null;
//待删除的节点中的元素
final E element = x.item;
//待删除节点的右边节点
//待删除的节点next指针指向的节点
final Node next = x.next;
//待删除节点的左边节点
//待删除的节点prev指针指向的节点
final Node prev = x.prev;
if (prev == null) {
//如果待删除节点的左边节点为null则说明待删除节点是头节点
//将待删除的节点next指针指向的节点设置为头节点(将待删除节点右边的节点设置为头节点)
first = next;
} else {
//如果待删除节点的左边节点不为null
//则将待删除节点的上一个节点的next指针指向待删除节点的下一个节点(将待删除节点的左边节点与待删除节点的右边节点关联)
prev.next = next;
//将待删除节点与左边节点取消关联
x.prev = null;
}
if (next == null) {
//如果待删除节点的右边节点为null则说明待删除节点是尾节点
//将待删除的节点prev指针指向的节点设置为尾节点(将待删除节点左边的节点设置为尾节点)
last = prev;
} else {
//如果待删除节点的右边节点不为null
//则将待删除节点的下一个节点的prev指针指向待删除节点的上一个节点(将待删除节点的右边节点与待删除节点的左边节点关联)
next.prev = prev;
//将待删除节点与右边节点取消关联
x.next = null;
}
//将待删除节点中的元素置为null
x.item = null;
//更新双向链表长度和修改次数
size–;
modCount++;
return element;
}
11.从尾节点开始查找指定元素第一个匹配到的元素的节点并删除(该方法和remove方法相似,一个是从头节点开始查找,一个是从尾节点开始查找)
public boolean removeLastOccurrence(Object o) {
if (o == null) {
for (Node x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
作者:答学网,转载请注明原文链接:http://www.dxzl8.com/