选对遍历方式比写对逻辑更早影响性能。数组遍历快慢取决于是否触发额外对象分配、重复读字段或破坏cpu缓存局部性;传统for循环是高频/大数组首选,jvm优化充分,无装箱拆箱和迭代器开销;显式缓存length可避免重复读取;排序后二分查找可提升吞吐;避免循环内远程调用、文件读写等耗时操作;禁止重复创建对象以减少gc压力。

选对遍历方式,比写对逻辑更早影响性能。数组本身是连续内存块,遍历快慢不取决于“能不能走完”,而取决于“怎么走”——是否触发额外对象分配、是否重复读字段、是否破坏CPU缓存局部性。
传统for循环:高频/大数组的首选
它是JVM优化最充分的方式,直接通过下标访问,无装箱拆箱、无迭代器对象创建。实测百万级 int[] 遍历耗时稳定在纳秒级。
- 显式缓存长度:写成 for (int i = 0, len = arr.length; i ,避免每次循环读取 arr.length 字段(虽JIT常能内联,但显式更可靠)
- 支持反向遍历或跳步:如 i += 2 或 i ,适合分段处理或偶数位提取
- 唯一自然获取索引的方式:适用于查找位置、构建新数组、原地修改等场景(注意:num = 100 在增强for中只改副本,无效)
增强for循环:简洁安全的只读遍历
对数组而言,它本质是语法糖,编译后仍转为基于索引的传统for,性能几乎持平,且自动规避 ArrayIndexOutOfBoundsException。
- 语义清晰:“我只关心每个值”,代码干扰少,可读性高
- 不能获取索引:若硬要记位置,需额外声明计数器变量,已失去简洁优势
- 不能修改原数组元素:循环变量是副本,赋值操作不影响原数组
Stream API:别为遍历而用
Arrays.stream(arr).forEach(...) 看起来酷,但背后有真实开销:创建Stream对象、包装IntStream、触发终端操作链路,还有基本类型装箱成本。
- 实测百万级 int[] 遍历,比传统for慢3–5倍,GC压力略高
- 仅建议用于真正需要函数式能力的场景:如 filter、map、sum、max 或 parallelStream
- 纯打印、累加、校验类操作,用Stream属于“杀鸡用牛刀”
大数组或热点路径下的隐藏细节
当数组长度达十万级以上,或在请求处理、实时计算等高频路径中反复遍历时,还需关注底层行为:
- 数据局部性:有序数组遍历通常更快——不是算法原因,而是CPU分支预测更高效;若循环含条件判断(如 if (x > threshold)),排序后可能提升数倍吞吐
- 避免循环内耗时操作:远程调用、文件读写、复杂对象构造,这些操作远比遍历本身慢几个数量级,应提前抽取或异步化
- 不要在循环里重复创建对象:比如每次new StringBuilder()或格式化日期,会显著增加GC压力
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











