选对循环结构本身不直接提升执行效率,真正影响性能的是循环内部逻辑、数据访问方式和整体设计;合理选择并优化可减少无效计算、降低时间复杂度、提升缓存友好性。

选对循环结构本身不直接提升执行效率,真正影响性能的是循环内部的逻辑、数据访问方式和整体设计。但合理选择循环类型并配合优化手段,能显著减少无效计算、降低时间复杂度、提升 CPU 缓存友好性。
按场景匹配最轻量的循环结构
不是“越高级越好”,而是“够用且可控”:
-
已知次数或索引遍历:优先用传统
for(int i = 0; i 。它结构清晰,JVM 易识别为计数循环(counted loop),便于自动展开(loop unrolling)和无关代码外提(loop-invariant code motion)。 -
遍历集合且无需索引:用增强型 for(
for (Type e : list))。它底层调用迭代器,语义简洁;但注意——若需在遍历时删除元素,必须用Iterator.remove(),否则抛ConcurrentModificationException。 -
条件驱动、次数未知:用
while。它比for少一次初始化和更新操作,适合状态机、I/O 等非数值型循环;但要确保循环变量在循环体内被修改,否则极易陷入无限循环。 -
必须至少执行一次:才用
do-while。实际业务中这类需求较少,过度使用反而增加理解成本,不建议为“省一次判断”而强行选用。
嵌套循环必须遵循“外小内大”原则
双重循环的时间复杂度是 O(外层次数 × 内层次数),但真实耗时还受 CPU 分支预测影响:
- 错误写法:
for (int i = 0; i —— 外层迭代太多,分支预测失败率高,实测慢一倍以上。 - 正确写法:
for (int i = 0; i —— 外层仅 10 次,CPU 预测成功率高,指令流水线更稳定。 - 若两层数据规模接近(如都是万级),优先考虑算法降维:用
HashSet替代内层遍历,将 O(n×m) 降至 O(n+m)。
循环体内必须做三件事减负
每次迭代都在重复执行,任何冗余都会被放大 N 倍:
-
提取循环不变量:把
list.size()、Math.sqrt(x)、config.getValue()等不随循环变化的表达式提到循环外。JVM 虽有优化,但显式提取更可靠、更易读。 -
避免在循环中创建对象:如
new String("abc")、new ArrayList()应提前声明复用,尤其在高频循环中,可大幅减少 GC 压力。 -
用
break和continue减少无效迭代:查找首个匹配项后立即break;跳过不符合前置条件的数据用continue,避免深层 if 嵌套。
超大数据量时,绕开循环本身
当数组/集合过大(如百万级),别只盯着怎么“优化 for”,先问是否必须用循环:
- 用
Stream API+ 并行流(parallelStream())适合 CPU 密集型、无状态操作,但要注意线程安全与装箱开销。 - 用
Arrays.binarySearch()或TreeSet替代内层线性搜索。 - 预处理数据:排序 + 双指针、哈希分桶、布隆过滤器等,让原本 O(n²) 的问题变成 O(n log n) 甚至 O(n)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











