1.3.1 底层双向链表结构
// 双向链表节点
private static class Node<E> {
E item; // 存储元素
Node<E> prev; // 前驱节点指针
Node<E> next; // 后继节点指针
Node(Node<E> prev, E element, Node<E> next) {
this.prev = prev;
this.item = element;
this.next = next;
}
}
transient Node<E> first; // 头节点
transient Node<E> last; // 尾节点
transient int size;
transient int modCount;
文字解释:双向链表保存头尾指针,头尾增删仅修改指针 O (1),按下标查找需要遍历。
1.3.2 按下标查找优化 node ()
Node<E> node(int index) {
// 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;
}
}
1.3.3 场景对比 ArrayList vs LinkedList
- 优先 ArrayList:随机查询、尾部新增、循环遍历(数组连续内存,CPU 缓存友好);
- 仅 LinkedList:频繁头尾插入删除、几乎无查询场景。