LinkList源码解析
数据结构
底层的数据结构就是双向链表。
LinkList的继承关系
一、类的继承关系
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
说明:LinkedList继承AbstractSequentialList抽象父类,实现了List接口(规定了List的操作规范)、Deque(双端队列)、Cloneable(可拷贝)、Serializable(可序列化)。
二、成员变量
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
// 内部类
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;
}
}
成员变量 transient关键字
持有对象的引用
比如,我们创建链表的结点如下。结点中持有前驱结点和后继结点的引用,引用就是对象在内存中的地址值。对于这样的结点形成的链表,我们序列化这个链表后,结点的前序和后继引用都失效了,因为内存地址变了。这种情况下我们需要重新连接链表。
序列化与反序列化
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
// 先调用默认的序列化方法
s.defaultWriteObject();
// 序列化容量
s.writeInt(size);
// 只把结点中的值序列化,前序和后继的引用不序列化
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
}
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
// 先调用默认的反序列化方法
s.defaultReadObject();
// 读容量
int size = s.readInt();
// 读取每一个结点保存的值,创建新结点,重新连接链表。
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
}
三、构造函数
public LinkedList() {}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
四、get(i)方法
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;
}
}
通过 index值,遍历范围 size 的前半/后半。
队列提供方法
Deque
Deque接口定义了在双端队列两端访问元素的方法.
第一个元素(头部) | 最后一个元素(尾部) | |||
---|---|---|---|---|
抛出异常 | 特殊值 | 抛出异常 | 特殊值 | |
插入 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
移除 | removeFirst() | pollFirst() | removeLast() | pollLast() |
检查 | getFirst() | peekFirst() | getLast() | peekLast() |
Queue
.LinkedList可以作为FIFO(先进先出)的队列,作为FIFO的队列时,下表的方法等价:
队列方法 | 等效方法 |
---|---|
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
stack
LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:
栈方法 | 等效方法 |
---|---|
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |