除了数组外,链表也是非常常用的数据结构,java里面的LinkedList就是实现了链表这一数据结构,而且它的底层是一个双向链表,下面是LinkedList的继承和实现结构
Queue
LinkedList实现了List和Deque这两个接口,List这个接口在上一篇Array中解释过了,Queue队列除了Collection的基础操作之外,还额外提供了插入、提取和检查操作,这些操作每一个都以两种方式存在,一种是失败时抛出异常,另一种是失败时返回一个值(null或者false)。
Queue的全部方法如下 其实Queue的方法都是成双成对的,虽然功能一样,但是出现异常时的处理不一样
功能 | 失败时抛出异常 | 失败时返回特殊值 |
---|
添加元素 | add | offer(失败时返回false) | 删除元素 | remove | poll(失败时返回null) | 获取队列头部元素 | element | peek(失败时返回null) |
Deque
Deque是用于构造支持两端元素插入和删除的线性集,这个接口定义了访问操作双端队列两端的方法,每一种方法也是以两种方式存在,同样是一种是错误时抛出异常,另一种是错误时返回特殊值
操作队列头部的函数是xxxFirst(),操作队列尾部的函数是xxxLast(),具体的功能看方法名就可以知道了 除此之外,Deque还提供了push和pop方法
LinkedList
链表中的基本元素由一个Node类包装,额外存储了前一个元素和后一个元素
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
看一下LinkedList的属性,既然是双端队列,那肯定是要存储第一个元素节点以及最后一个元素系欸D节点
transient Node<E> first;
transient Node<E> last;
添加元素
向头部添加一个节点
public void addFirst(E e) {
linkFirst(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)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
这个就是实现了一个链表的基本添加操作了,向最后一个节点添加元素也是同理
删除元素
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
private E unlinkLast(Node<E> l) {
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null;
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
这里的删除操作仍然是基本的链表删除操作,删除第一个节点也是同理
检索
java的LinkedList实现于普通的链表有所不同,因为实现了List接口,所以它也是支持检索的,可以通过索引来获取节点
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int 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;
}
}
|