LinkedList的node(int index)方法采用双向遍历策略:根据index与size/2的大小关系,决定从头或尾开始线性遍历,时间复杂度仍为O(n),仅常数因子优化,并非位运算寻址。

Java 中 LinkedList 的 node(int index) 方法并不会使用位移运算来“缩小遍历范围”,它采用的是**双向遍历策略**:根据目标索引离头尾的远近,决定从头(first)还是从尾(last)开始遍历,从而将最坏遍历步数从 n 降到 n/2。这里没有位运算参与计算,所谓“位移”是常见误解。
为什么不是位移,而是比较中点?
node(index) 的核心逻辑是判断 index 是否小于 size >> 1(即 size / 2 的整数除法),这个 >> 是位移,但仅用于高效计算中点位置,并非用于“跳着寻址”或“二分式定位”。LinkedList 是链表结构,不支持随机访问,无法像数组那样通过地址偏移直接定位元素。
它的实现本质仍是线性遍历,只是做了方向优化:
- 若
index < size/2:从头节点first向后遍历index步; - 否则:从尾节点
last向前遍历size - 1 - index步。
源码关键逻辑(JDK 8+)
简化后的关键片段如下:
立即学习“Java免费学习笔记(深入)”;
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;
}
}其中 size >> 1 等价于 size / 2(对非负整数),只是 CPU 层面更快,但它不改变遍历的线性本质,也不跳过节点。
和 ArrayList 的本质区别
ArrayList 支持 O(1) 随机访问,靠的是数组下标直接计算内存偏移:elementData[index];
LinkedList 即使加了方向优化,仍是 O(n) 时间复杂度,平均耗时约 O(n/2),常数因子减半,但渐进复杂度未变。
试图用位运算“加速链表寻址”在原理上不可行——链表节点物理地址不连续,无法通过位移推导地址关系。
什么情况下你会误以为用了“位移寻址”?
可能混淆了以下概念:
-
size >> 1是算中点,不是跳节点; - 某些并发数据结构(如
ConcurrentLinkedQueue)或自定义跳表(SkipList)会用多级指针,但标准LinkedList没有; - 位运算常被误认为“底层高效=智能跳转”,其实这里只是替代除法的常规优化。
不复杂但容易忽略:链表的“快”,只体现在增删首尾的 O(1),访问任意位置永远绕不开逐个链接。选对数据结构,比琢磨怎么让 LinkedList 变快更重要。


















