linkedlist是双向链表,get(i)为o(n);arraylist是连续数组,get(i)为o(1),故randomaccess接口仅作标记;应通过instanceof判断后选择for或迭代器遍历。

看懂底层结构,才能选对遍历方式
LinkedList 是双向链表,每个节点存数据 + 前驱指针 + 后驱指针;访问第 i 个元素必须从头或尾开始逐个跳转,get(i) 时间复杂度是 O(n)。而 ArrayList 是数组,内存连续,通过索引可直接计算地址,get(i) 是 O(1) —— 这就是 RandomAccess 接口存在的根本原因:它不提供方法,只标记“支持快速随机访问”。
用 instanceof 判断是否支持 RandomAccess
别硬记哪个类该用哪种循环,运行时判断最稳妥:
-
if (list instanceof RandomAccess) → 用普通 for 循环(
for (int i = 0; i ) -
else → 用增强 for 或显式 Iterator(
for (E e : list)或Iterator<e> it = list.iterator(); while(it.hasNext()) it.next();</e>)
这个判断在工具方法、泛型集合处理中非常实用,避免把 LinkedList 当 ArrayList 用导致性能暴跌。
实测差距远超想象:100 万数据下典型耗时
以真实测试为依据(JDK 17+,HotSpot,禁用 JIT 预热干扰):
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
-
ArrayList(RandomAccess):
– 普通 for:≈ 4.5 ms
– 增强 for / Iterator:≈ 6.2–7.0 ms -
LinkedList(非 RandomAccess):
– 普通 for(含 get(i)):≈ 140–180 ms(因每次 get 都要遍历链表)
– 增强 for / Iterator:≈ 9–11 ms(迭代器直接沿 next 指针走,O(1) 移动)
注意:增强 for 对 LinkedList 来说,本质就是调用 iterator,不是语法糖的“慢”,而是底层适配得好。
特殊场景别踩坑:边遍历边修改怎么办
如果遍历中需要删除当前元素或插入到当前位置附近:
- ArrayList:优先用 Iterator.remove(),避免并发修改异常;但 remove(i) 会触发数组搬移,开销大
- LinkedList:它的 ListIterator 支持
add()、remove()、set(),全部是 O(1),这才是它不可替代的优势场景——比如解析日志流时动态过滤+插桩
此时哪怕用的是 LinkedList,也别用 for + get(i) 再 remove(i),那等于双重 O(n)。










