我是个木得感情的更新机器
// 链表的表头,表头无数据。Entry是个链表类数据结构,详细明细请看后面。
private transient Entry header = new Entry(null, null, null);
// LinkedList中元素个数,即当前容量
private transient int size = 0;
包含三个属性:上一节点,下一节点,节点值。
从这里可以看出,LinkedList其实是一个双向链表,可以向前后两个方向获取。
private static class Entry {
// 当前节点的值
E element;
// 下一个节点
Entry next;
// 上一个节点
Entry previous;
//节点的构造函数。
Entry(E element, Entry next, Entry previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
获取LinkedList中指定位置的节点,每次都从头或者尾开始查找,效率最低。因此,在遍历时劲量不要使用这种方式,应该使用迭代器或者for each方式。
private Entry<E> entry(int index) {
if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size);
Entry<E> e = header;
// 获取index处的节点。
// 若index 小于长度的1/2,则从前先后查找
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
// 否则,从后向前查找
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
遍历时初始化迭代器从头或尾开始找到位置,之后使用每次只查询下一个即可。
private class ListItr implements ListIterator<E> {
// 上一次返回的节点 private Entry lastReturned = header;
// 下一个节点
private Entry<E> next;
// 下一个节点对应的索引值
private int nextIndex;
// 预期的改变次数。用来实现fail-fast机制。 private int expectedModCount = modCount;
// 构造函数。
// 从index位置开始进行迭代
ListItr(int index) {
// index的有效性判断
if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size);
// 若 index 小于双向链表长度的一半,则从第一个元素开始往后查找;
if (index < (size >> 1)) {
next = header.next; for (nextIndex=0; nextIndex<index; nextIndex++)
next = next.next;
} else {
// 否则,从最后一个元素往前查找
next = header; for (nextIndex=size; nextIndex>index; nextIndex--)
next = next.previous;
}
}
// 实现fail-fast机制,前文说过。
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException();
}
}
先写入容量,再写具体值;
先读出容量,再读出每个具体值
// 将LinkedList的容量,元素值都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
// 写入容量
s.writeInt(size);
// 将链表中所有节点的值都写入到输出流中 for (Entry e = header.next; e != header; e = e.next)
s.writeObject(e.element);
}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
// 从输入流中获取容量
int size = s.readInt();
// 新建表头节点
header = new Entry<E>(null, null, null);
header.next = header.previous = header;
// 从输入流中将“所有值”并逐个添加到链表中
for (int i=0; i<size; i++) addBefore((E)s.readObject(), header);
}