2012-03-20 110 views
5

几乎所有与ArrayList容量有关的问题都是如何使用它或(奇怪地)访问它,我对这些信息非常熟悉。我感兴趣的是它是否真的值得使用ArrayList构造函数来设置容量,如果你碰巧知道或者有一个大概的想法,ArrayList中有多少项目?为什么要使用ArrayList(int容量)?

是否有任何综合性的基准比较了如何使用天真添加元素到ArrayList与预先设置ArrayList的容量需要多长时间?

+3

当达到该ArrayList的容量,CLR创建一个与原始一个从原来的一个新创建的双重能力,并将所有元素的新的ArrayList一。因此,如果您有一些与所需大小有关的想法,则可以通过预先设置ArrayList的大小来保存这些额外的工作。 – 2012-03-20 03:53:56

+1

@Deepansh:这不是Java问题吗? CLR是如何进入画面的?我想你的意思是JVM?此外,您的描述似乎正确,但“在CLR”(.Net)中,预先分配大小时需要更多时间。至少,这是在我测试1000000个项目时发生的情况。我测试了10-15次,每次默认的ArrayList构造函数都赢了! – TCM 2012-03-20 03:59:05

+0

我说ArrayList,但它可以适用于概念,通常有一个由数组内部支持的集合的列表视图。 – Maverick 2012-03-20 04:02:06

回答

6

很明显,对于任何特定的应用程序,您必须测试任何性能调整以确定它们是否实际上是优化的(并且实际上是否有必要),但有时候显式设置容量可能是值得的。例如:

  • 您正在创建大量的数组列表,其中大多数数组列表非常小。在这种情况下,您可能希望将初始容量设置得非常低,并且/或者在完成填充给定数组时填充容量。 (在这种情况下,优化不是速度问题,而是内存使用情况,但请注意,列表本身具有内存开销,它所包含的数组也是如此,因此在这种情况下,重新设计可能会更好一种方式,有较少的名单。)
  • 你正在创建一个非常大已知大小的数组列表,并且要及时补充每个元素是非常小的(也许是因为每次时间添加一个元素,你必须发送一些响应给外部数据源)。 (默认几何增长需要分期付款固定时间:每过一段时间,都会产生巨大的损失,因此整体平均表现完全正常,但如果您关心的是个别插入,可能不够好)
+0

这是一个很好的答案 – mfrankli 2012-03-20 04:10:11

1

ArrayList内部使用简单的数组来存储其元素,如果元素的数量超过了底层数组的容量,需要调整大小。因此,如果您知道List包含多少项目,您可以通知ArrayList使用所需大小的数组,因此不需要或执行调整大小逻辑。

3

我没有什么实质性的增加到ruakh的答案,但这里有一个快速测试功能。我写了一个废料项目来写这样的小测试。调整sourceSize以代表您的数据,并且可以大致了解效果的大小。如图所示,我看到他们之间的因素是2。

import java.util.ArrayList; 
import java.util.Random; 

public class ALTest { 
    public static long fill(ArrayList<Byte> al, byte[] source) { 
     long start = System.currentTimeMillis(); 
     for (byte b : source) { 
      al.add(b); 
     } 
     return System.currentTimeMillis()-start; 
    } 
    public static void main(String[] args) { 
     int sourceSize = 1<<20; // 1 MB 
     int smallIter = 50; 
     int bigIter = 4; 

     Random r = new Random(); 
     byte[] source = new byte[sourceSize]; 
     for (int i = 0;i<bigIter;i++) { 
      r.nextBytes(source); 
      { 
       long time = 0; 
       for (int j = 0;j<smallIter;j++) { 
        ArrayList<Byte> al = new ArrayList<Byte>(sourceSize); 
        time += fill(al,source); 
       } 
       System.out.print("With: "+time+"ms\t"); 
      } 
      { 
       long time = 0; 
       for (int j = 0;j<smallIter;j++) { 
        ArrayList<Byte> al = new ArrayList<Byte>(); 
        time += fill(al,source); 
       } 
       System.out.print("Without: "+time+"ms\t"); 
      } 
      { 
       long time = 0; 
       for (int j = 0;j<smallIter;j++) { 
        ArrayList<Byte> al = new ArrayList<Byte>(); 
        time += fill(al,source); 
       } 
       System.out.print("Without: "+time+"ms\t"); 
      } 
      { 
       long time = 0; 
       for (int j = 0;j<smallIter;j++) { 
        ArrayList<Byte> al = new ArrayList<Byte>(sourceSize); 
        time += fill(al,source); 
       } 
       System.out.print("With: "+time+"ms"); 
      } 
      System.out.println(); 
     } 
    } 
} 

输出:

With: 401ms Without: 799ms Without: 731ms With: 347ms 
With: 358ms Without: 744ms Without: 749ms With: 342ms 
With: 348ms Without: 719ms Without: 739ms With: 347ms 
With: 339ms Without: 734ms Without: 774ms With: 358ms