You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两种List遍历for循环写法的性能差异及JVM优化问题

两种List遍历for循环的区别、性能与JVM优化解析

首先先修正下你代码里的小疏漏——两种写法里的list.size都应该是list.size()(调用方法,不是直接访问字段),先把正确的写法列出来:

  • 写法1:for(int i=0, length=list.size(); i<length; i++)
  • 写法2:for(int i=0; i<list.size(); i++)

核心逻辑区别

这两种写法最本质的差异在于list.size()的调用次数:

  • 写法1会在循环开始前,一次性调用list.size()并把结果存在局部变量length里,整个循环过程中不会再调用size()方法。
  • 写法2会在每次循环的条件判断阶段都调用一次list.size(),也就是循环迭代多少次,size()就被调用多少次。

这个差异会直接影响两种写法的行为:

  • 如果循环过程中List的元素数量不会变化(比如用ArrayList且循环内没有add/remove操作),那两种写法逻辑完全等价,遍历的结果一致。
  • 如果循环过程中List的元素数量会动态改变(比如循环里有删除元素的操作),写法2会每次取最新的size,而写法1用的是循环开始时的初始size。举个例子:如果循环里删除了元素,写法2会因为size变小提前结束循环,而写法1可能会继续循环到初始的length,导致出现IndexOutOfBoundsException。

性能差异分析

性能差异取决于list.size()方法的实现:

  • 对于Java标准库中的大多数List(比如ArrayList、LinkedList),size()是O(1)操作——内部维护了一个专门的size变量,调用时直接返回这个变量的值,几乎没有开销。这种情况下两种写法的性能几乎没差别,哪怕循环个几十万次,差距也微乎其微。
  • 但如果是自定义的List实现,或者某些特殊的List(比如需要实时计算元素数量的包装类),size()是O(n)操作(比如每次都要遍历整个集合统计元素),那写法1的性能会碾压写法2——写法1只计算一次size,时间复杂度是O(n);写法2每次循环都要计算size,时间复杂度会变成O(n²),数据量大的时候差距会非常明显。

JVM会做优化吗?

HotSpot这类主流JVM的JIT(即时编译器)会做循环不变量消除优化——如果JVM能确定list.size()在循环过程中不会发生变化(比如List是局部变量,循环内没有修改List的操作,也没有其他线程可能修改它),那么JVM会自动把list.size()的调用提前到循环外面,相当于把写法2优化成写法1的样子。

但这个优化不是100%会生效:

  • 如果List是全局变量、或者被其他线程引用、或者循环内有可能修改List的操作(哪怕实际没执行),JVM就无法确定size是否会变化,也就不会做这个优化。
  • 对于那些size()是O(n)的自定义List,JVM通常也无法识别到它的耗时,所以不会主动优化,这时候还是得手动用写法1来提升性能。

总结

  • 当List在循环中不会被修改时,两种写法逻辑等价,性能在JVM优化后几乎一致;
  • 当List在循环中会动态变化时,两种写法的行为完全不同,需要根据业务需求选择;
  • 当size()是耗时操作时,写法1的性能更优,且JVM不一定能自动优化写法2,建议手动提前缓存size值。

内容的提问来源于stack exchange,提问作者lian chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:33:21