我应该避免在循环中获取集合的大小吗?

Should I Avoid Getting the Size of a Collection in a Loop?

根据第 3 处的 https://www.geeksforgeeks.org/12-tips-to-optimize-java-code-performance/,它说在 for 循环期间,您应该预先定义大小并在比较器中调用它。起初,假设 .size() 方法每次调用时都必须对元素进行计数,这对我来说是有意义的。

为了验证这一点,我查看了 ArrayList 的源代码并查看了 size 方法。但我发现它只是 return 一个整数大小,作为值存储在对象中。这更多的是我期待找到的东西,但如果是这样的话,那为什么文章说要避免呢?它没有解释为什么,它只是说永远不要这样做。据我所见,该列表已经在调用存储在内存中的变量。

所以,我的问题是:实际上 会有所帮助,还是只是文章有误?

是的,它实际上会有所帮助。 我认为调用一个方法比使用一个变量花费更多的时间。

答案是:“视情况而定”。

  • 这取决于您使用的 List class。
  • 这取决于 JIT 编译器的智能程度。
  • 这取决于在循环执行过程中列表的大小是否发生变化。

对于最常见的 List 实现,当前大小保存在一个字段中,而 size() 方法只是 returns 该字段。在这种情况下,size() 方法的代码通常会被内联,因此 size() 调用与直接访问该字段一样高效。如果 JIT 编译器能够推断出该字段没有改变(并且如果没有相关的 Java 内存模型相关约束)那么它可以想象将 size() 结果缓存在寄存器中。

但不利的一面是,某些 List 实现可能 计算 大小,而 JIT 编译器可能无法进行部分或全部优化。

但不利的一面是,如果 size() 很便宜,那么在每次循环迭代中调用它的开销可能太小而不重要。


底线:

  • 谨防过早优化

  • 提防提供过于简单化/过于笼统建议的文章。

  • 谨防包含 胡说八道 的文章,例如:

    If possible, we can use primitive types instead of objects since data access from stack memory is faster than heap memory1.


1 - 这出现在 "5. 尽可能使用基本类型"。栈内存和堆内存使用相同的硬件,访问时间也相同。在这种情况下,他应该提出的真正要点是,与访问 int.

相比,获取 Integer 的值涉及额外的内存获取