list.clear()vs list = new ArrayList <Integer>();

Gre*_*reg 120 java arraylist

清除ArrayList的两个选项中哪一个更好更快,为什么?

list.clear() 
Run Code Online (Sandbox Code Playgroud)

要么

list = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)

碰巧我必须在随机的时间清除我的ArrayList中的所有条目,我无法知道将来会有多少新条目,可能有0或1000.哪种方法更快更好,为什么?

dfb*_*dfb 74

没有基准测试很难知道,但如果你的ArrayList中有很多项目并且平均大小较低,那么创建一个新的ArrayList可能会更快.

http://www.docjar.com/html/api/java/util/ArrayList.java.html

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}
Run Code Online (Sandbox Code Playgroud)

  • +1用于显示来源.值得注意的是,`clear`*不会调整后备阵列的大小. (32认同)
  • 注意,新的ArrayList也需要O(n)时间 - 新的Object [n]需要对每个插槽进行归零. (11认同)
  • @pst:这是一个有趣的观点 - 如果ArrayList将被清除并重复填充数百个项目,使用`.clear()`可能会更快,从而防止在大小超过容量时发生的阵列复制在`.add(Object)`调用. (8认同)
  • @PlatinumAzure:这不是一个明确的优势,因为你可以设置ArrayList的初始容量? (4认同)
  • @irreputable - 但是,一个区别是clear()使用显式循环(在Java中)执行操作,但是对于`new Object [n]`,使用大容量内存清零机制由GC完成归零更快; 例如,手动优化的C++或ASM,甚至是聪明的虚拟内存技巧. (4认同)

Nat*_*hes 25

List.clear 将删除元素而不降低列表的容量.

groovy:000> mylist = [1,2,3,4,5,6,7,8,9,10,11,12]
===> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
groovy:000> mylist.elementData.length
===> 12
groovy:000> mylist.elementData
===> [Ljava.lang.Object;@19d6af
groovy:000> mylist.clear()
===> null
groovy:000> mylist.elementData.length
===> 12
groovy:000> mylist.elementData
===> [Ljava.lang.Object;@19d6af
groovy:000> mylist = new ArrayList();
===> []
groovy:000> mylist.elementData
===> [Ljava.lang.Object;@2bfdff
groovy:000> mylist.elementData.length
===> 10
Run Code Online (Sandbox Code Playgroud)

这里mylist被清除了,对它所持有的元素的引用被删除了,但它保留了相同的后备数组.然后mylist重新初始化并得到一个新的后备阵列,旧的得到了GCed.因此,一种方式保留在内存中,另一种方式抛出其内存并从头开始重新分配(使用默认容量).哪个更好取决于您是否要减少垃圾收集流失或最小化当前未使用的内存量.列表是否足够长以便移出伊甸园可能是决定哪个更快的一个因素(因为这可能使垃圾收集更加昂贵).


Ste*_*n C 19

我认为答案是它取决于一系列因素,例如:

  • 是否可以预先预测列表的大小(即,您是否可以准确设置容量),
  • 列表大小是否可变,
  • 列表的生命周期在两个版本中都有多长,和
  • 你的堆/ GC参数和CPU.

这些使得很难预测哪个更好.但我的直觉是差异不会那么大.

两点建议:

  • 不要浪费时间尝试优化这个...除非应用程序客观上太慢>>和<<分析器告诉你这是一个性能热点.(很可能这些先决条件中的一个或另一个不是真的.)

  • 如果你决定优化它,那就科学地做.尝试两种(所有)备选方案,并通过在实际问题/工作负载/输入集上测量实际应用程序的性能来确定哪种方案最佳.(由于上面列出的因素,人工基准测试不太可能为您提供可以使用的答案.)


RMT*_*RMT 15

第一个.clear();将保持相同的列表清除列表.

第二个在内存中new ArrayList<Integer>();创建一个新ArrayList的.

建议:首先是因为这就是设计目的.

  • 当然,`clear`旨在清除列表 - 但是从根本上来说,这比使用*new*空列表更好? (5认同)

小智 5

尝试了以下程序,同时采用了两种方法。1.在for循环中清除arraylist obj。2.在for循环中创建新的New Arraylist。

List al= new ArrayList();
        for(int i=0;i<100;i++)
        {
            //List al= new ArrayList();

            for(int j=0;j<10;j++)
            {
                al.add(Integer.parseInt("" +j+i));
                //System.out.println("Obj val " +al.get(j));
            }
            //System.out.println("Hashcode : " + al.hashCode());
            al.clear();

        }
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是 内存分配没有太大变化。

使用新的Arraylist方法。

循环前总可用内存:64,909 ::

After循环后的总可用内存:64,775 ::

采用清晰的方法

循环前总可用内存:64,909 ::循环后总可用内存:64,765 ::

因此,从内存利用率的角度来看,使用arraylist.clear并没有太大区别。

  • IMHO 10和100太小了,无法测试。 (8认同)