代码之家  ›  专栏  ›  技术社区  ›  Peterdk

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

  •  16
  • Peterdk  · 技术社区  · 16 年前

    我在想,是不是 size() ArrayList<T> 缓存? 或者在性能关键型代码中,我只存储 用本地int?

    当您不在对的调用之间添加/删除项时,我希望它确实是缓存的 .

    我说得对吗?


    我不是在说内联之类的东西。我只想知道 大小() 它本身在内部缓存值,或者每次调用时动态计算。

    7 回复  |  直到 16 年前
        1
  •  13
  •   Jon Skeet    16 年前

    我不认为它是“缓存”的,但它只是存储在一个字段中,所以它的速度足够快,可以频繁调用。

    size() 只是:

    public int size() {
        return size;
    }
    
        2
  •  5
  •   Timothy    16 年前

    对。

    快速查看Java源代码可以告诉您答案。

        3
  •  2
  •   polygenelubricants    16 年前

    这是中的实现 OpenJDK version

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

    所以它和方法调用一样好。热点不太可能缓存此方法返回的值,因此 你可以自己把它藏起来。除非分析表明这是一个瓶颈(不太可能),否则您应该关注可读性,而不是返回字段值的简单方法调用是否被缓存。

        4
  •  2
  •   Michael Aaron Safyan    16 年前

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

    编辑

        5
  •  0
  •   Marcelo Cantos    16 年前

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

        6
  •  0
  •   unwind    16 年前

    为什么要这样?毕竟,ArrayList实现了一个由数组支持的列表接口。

    我想它只是有一个 size

    不过,我现在只看了API文档。

        7
  •  0
  •   finnw    16 年前

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