2012-03-20 111 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