2015-02-05 34 views
5

我是一個有點經驗的Java開發人員,我一直看到這樣的事情創建初始容量爲0的ArrayList的優點?

List<Integer> l = new ArrayList<Integer>(0); 

,我實在無法理解。當你知道它將超出容量時,創建一個初始容量爲0的ArrayList有什麼意義?

這樣做有任何已知的好處嗎?

+0

[ArrayList al = new ArrayList()之間的區別是什麼?和ArrayList al = new ArrayList(0)?](http://stackoverflow.com/questions/4666024/what-is-the-difference-between-arraylist-al-new-arraylist-and-arraylist-al) – Ascalonian 2015-02-05 13:46:25

+0

也:[爲什麼啓動一個初始容量ArrayList?](http://stackoverflow.com/questions/15430247/why-start-an-arraylist-with-an-initial-capacity) – Ascalonian 2015-02-05 13:47:40

+2

@Ascalonian我真的知道它的區別,我想知道的是這樣做的好處,而不是做'新ArrayList ()'。不是一個重複。 – Mauren 2015-02-05 13:47:52

回答

5

它使ArrayList非常小的尺寸(在內存中),是當你想要的變量爲非空,並準備使用,戰術但不要指望List立即填充。如果你期望它立即被填充,最好給它一個更大的初始值 - ArrayList的任何「增長」都是在內部創建一個新的基本數組,並複製項目。 ArrayList的增長很昂貴,應該儘量減少。

或者,如果您正在創建批次類別的實例,每個實例都包含這些List屬性中的一個。如果您沒有立即計劃填寫它們,您可以通過不分配房間來節省一點內存。

但是:還有更好的辦法:Collections.emptyList()。通常情況下,您需要直接保護對該列表的訪問,並且(例如)在您的課堂上提供在內部List上運行的特定於域的方法調用。例如,假設您有一個包含List學生姓名的School類。 (保持簡單。)

public class School { 
    private List<String> studentNames = Collections.emptyList(); 

    public void addStudentName(String name) { 
     if (studentNames.isEmpty()) { 
      studentNames = new ArrayList<String>(); 
     } 
     studentNames.add(name); 
    } 

    public void removeStudentName(String name) { 
     studentNames.remove(name); 
     if (studentNames.isEmpty()) { 
      studentNames = Collections.emptyList(); // GC will deallocate the old List 
     } 
    } 
} 

如果你願意讓isEmpty()檢查和執行初始化/分配,這是創建大量空ArrayList實例的一個更好的選擇,因爲Collections.emptyList()是一個靜態實例(只有一個存在)並且不可修改。

-2

根據合同,您可以通過不具有空值來避免NullPointerExceptions。這是在某些情況下很好的做法,看到有效的Java由約書亞布洛赫項目43:返回空數組或集合,而不是空值

+2

'new ArrayList <>()'也是一個空列表... – Steffen 2015-02-05 13:53:46

+0

顯然,問題是沒有對比ArrayList <>()vs ArrayList <>(),但是要求使用ArrayList <>(0)的一般原因。當然,還有其他選擇。 – barq 2015-02-05 14:07:40

1

它總是更好的方法來給出一個較大的值(如果你有多少名單將超過)到數組列表,因爲它會減少列表的大小調整,從而優化執行時間。

與價值0初始化數組列表創建,如果你知道哪些reducing memory列表不會出現更多的則10內容的Empty數組列表。

+0

是的,它是正確的,而不是保持null值在你的數組列表初始化爲零。 – 2015-02-06 09:03:34

+0

@vikingsteve感謝您的回覆,我編輯了我的答案。 – 2015-02-06 11:54:21

+0

好的,我刪除了我的downvote。現在你的答案好多了,謝謝你花時間再次編輯它。 – vikingsteve 2015-02-06 12:09:22

6

對於Java (或OpenJDK 7的),而不是指定的初始大小給你設置爲初始大小內的列表。因此,根據您使用列表的很多因素,初始化大小爲0的列表的內存和/或性能可能會稍高一點。

對於java ,指定初始大小0在功能上等同於不指定初始大小。

但是它實際上是效率較低,因爲調用與參數0構造行爲給new Object[0]一個電話,而如果指定無參數的構造函數,對列表中的初始elementData設置爲靜態定義的常量命名EMPTY_ELEMENTDATA。從ArrayList

相關代碼:

/** 
* Shared empty array instance used for empty instances. 
*/ 
private static final Object[] EMPTY_ELEMENTDATA = {}; 

換句話說,使用new ArrayList<Integer>(0);似乎是多餘的,也有這樣做沒有任何好處,而且我會用new ArrayList<Integer>();代替。

+0

這對於openjdk 7來說是正確的。對於打開的jdk 6不是如此,請參閱http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList。 java /?v = source – henry 2015-02-05 13:57:15

+0

對於OpenJDK 7的所有*版本,甚至都不是這樣,它看起來像:http://grepcode.com/file/repository.grepcode。com/java/root/jdk/openjdk/7-b147/java/util/ArrayList.java但是我再也不知道grepcode究竟有多精確...... – 2015-02-05 14:01:51

+0

謝謝你們,我更新了我的回答。 – vikingsteve 2015-02-05 14:03:56

3
  • 如果添加到ArrayList真的不太可能,如果它保持ArrayList的大小至少是很重要的,那麼我可以看到,是有用的。

  • 或者如果ArrayList的唯一目的是從方法返回值,返回空列表是給函數調用方的特殊消息,如「找不到結果」。

  • 否則,不是真的。

1

默認ArrayList的容量爲10,每次調整大小+ 50%。

通過使用較低的初始容量,您可以有時(理論上)節省內存。另一方面,每次調整大小都很耗時。在大多數情況下,這只是搶先優化的一個標誌。

+0

這也是我也想到的,但是剛剛檢查了openjdk 7的源代碼,它現在通過使用@vikingsteve描述的共享空元素進行優化。 – henry 2015-02-05 14:06:24