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

时间:2010-05-18 11:39:51

标签: java arraylist caching

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

如果您在调用size()之间不添加/删除项目,我希望它确实可以缓存。

我是对的吗?

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

7 个答案:

答案 0 :(得分:12)

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

size()的Sun JDK实现只是:

public int size() {
    return size;
}

答案 1 :(得分:4)

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

这是OpenJDK version中的实施:

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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

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

答案 6 :(得分:0)

如果缓存size()方法的结果会显着提高性能(有时会这样做 - 我会经常看到ArrayList.size()作为我-Xprof输出中的顶级编译方法)然后考虑转换整个列表到一个数组,以获得更大的加速。

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

class FooProcessor {

    private Foo[] fooArray = null;
    private List<Foo> fooList = new ArrayList<Foo>();

    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;
    }

}