是否缓存了ArrayList.size()方法?

我想知道,是否可以在现有的ArrayList缓存上调用size()方法? 或者,在性能关键代码中,我只将size()存储在本地int中是否更可取?

当你不在调用size()之间添加/删除项目时,我希望它确实被缓存。

我对吗?

更新
我不是在谈论内联或类似的事情。 我只是想知道方法size()本身是否在内部缓存值,或者它是否在每次调用时动态计算。

我认为我不会说它是“缓存”的 – 但它只是存储在一个字段中,所以它足够快,可以经常调用。

size()的Sun JDK实现只是:

 public int size() { return size; } 

是。

快速浏览Java源代码可以告诉您答案。

这是OpenJDK版本中的实现:

 /** * Returns the number of elements in this list. * * @return the number of elements in this list */ public int size() { return size; } 

所以它和方法调用一样好。 HotSpot不太可能缓存此方法返回的值,因此如果你真的关心它,你可以自己缓存它。 除非你的分析表明这是一个瓶颈,但是(不太可能),你应该只关心自己的可读性,而不是一个简单的方法调用返回一个字段的值是否被缓存。

我肯定不知道答案,但我的猜测是:不。 Java编译器(缺少特殊的套接字ArrayList)无法知道您调用的函数将是非变异的,因此,size()的调用应该返回相同的值。 因此,我发现Java编译器不太可能将重复调用size()并将它们存储在临时值中。 如果您需要这种级别的优化,那么您应该自己将值存储在本地变量中。 否则,是的,您将支付与调用size()方法相关的函数调用开销。 但请注意,对于ArrayList,size()方法是O(1)(尽管函数调用开销非常大)。 就个人而言,我会从循环中分解出对size()的任何调用,并在适用的地方手动存储它们。

编辑
尽管Java编译器无法执行这样的优化,但已恰当地指出JIT可以内联ArrayList.size()的实现,这样它只需要与字段访问相同,而无需任何额外的方法调用开销,所以实际上成本可以忽略不计,尽管你可能仍然可以通过手动保存一个临时值来节省一些(这可能会消除内存查找,而是从CPU寄存器中提供变量)。

ArrayList的明显实现是将字段内部存储在字段中。 如果必须计算,即使在resize后,我会感到非常惊讶。

为什么需要? 毕竟,ArrayList实现了一个由数组支持的List接口。

我假设它只有一个size成员,当你插入东西时递增,当你删除时递减,然后它只返回它。

不过,我现在还没有看过比API文档更多的内容。

如果缓存size()方法的结果会显着提高性能(有时-Xprof – 我经常看到ArrayList.size()作为我-Xprof输出中的顶级编译方法)然后考虑将整个列表转换为数组甚至更快的加速。

如果您定期迭代列表但很少更新它,这里有一个可行的技巧:

 class FooProcessor { private Foo[] fooArray = null; private List fooList = new ArrayList(); public void addFoo(Foo foo) { fooList.add(foo); fooArray = null; } public void processAllFoos() { Foo[] foos = getFooArray(); for (int i = 0; i < foos.length; ++ i) { process(foos[i]); } } private void getFooArray() { if (fooArray == null) { Foo[] tmpArray = new Foo[fooList.size()]; fooArray = fooList.toArray(tmpArray); } return fooArray; } }