簡體   English   中英

設置不總是使用的ArrayList的初始容量的最佳實踐是什么?

[英]What is the best practice for setting the initial capacity of an ArrayList that is not always used?

我有一些類具有有時僅使用的ArrayList字段。 我通常像這樣初始化這些字段:

private List<Widget> widgets = new ArrayList<>();

我了解使用重載構造函數來設置初始容量的原因,所以我想知道是否應該這樣聲明這些字段:

private List<Widget> widgets = new ArrayList<>(0);

難題是,如果我使用0初始化列表,那么列表將總是不得不重新初始化自身以添加甚至一項。 但是,如果我使用默認構造函數(其默認容量為10),那么我可能會有很多項目(可能有很多)浪費了未使用的容量的內存。

我知道你們中的一些人會推遲詢問“多久一次”和“期望多少個項目”,但我確實在尋找“最佳實踐”方法。 所有事物都是相等的,應該在有時使用的列表上用(0)()初始化嗎?

始終初始化列表是我們的部門政策,因此我可能不會簡單地將列表保留為null ,而且只會回避此問題。

過早的優化是萬惡之源。 -D. Knuth。

這似乎是一種“性能問題”,實際上對性能沒有任何影響。 一方面,您如何確定這些空列表實際上已初始化? 我懷疑大多數現代編譯器都會延遲對象的初始化,直到他們確定將對它們進行調用為止。 因此,如果您傳遞no arg構造函數,則除非將某些內容添加到列表中,否則極有可能永遠不會使用它。 另一方面,如果使用0參數構造函數,則它保證必須調整其使用的每個大小。

這是性能優化的三個定律

  1. 永遠不要以為您知道編譯后的代碼實際上在做什么,或者不要以比編譯器更好的方式進行小的優化。
  2. 在沒有使用探查器找出瓶頸所在的情況下,切勿進行優化。 如果您認為自己知道,請參考規則編號(1)。
  3. 除非您的應用程序出現性能問題,否則請不要打擾。 然后參考規則(2)。

如果您仍然以某種方式仍然相信自己對編譯器有所了解,請檢查以下問題: 為什么處理排序數組比未排序數組更快?

如果列表不總是使用,請使用延遲初始化

private List<Widget> widgets;

private List<Widget> getList() {
    if (widgets == null) {
         widgets = new ArrayList<>();
    }
    return widgets;
}

如果將其設置為0,則ArrayList必須以任何方式調整大小,因此,實際上您是在射擊自己。 唯一會受益於顯式聲明大小的方法是,如果您已經知道列表中將達到的最大范圍。

如前所述,這是一個微優化,比起ArrayList的初始大小,您更有可能發現其他可以顯着改進的東西。

我不同意這些優化是不好的 如果您聲明一個包含n個元素的arraylist(如果我沒記錯的話,默認為第8個),然后再放一個,則arraylist在內部會將其容納的大小加倍。 以后刪除此元素時,列表不會減少

ArrayList充分利用了處理器緩存,並且實際上是如此之快,以至於您無需進一步優化它。 不過,如果您必須創建數百萬個微小的ArrayList實例,則可能值得考慮重新設計整體設計,而不必理會默認AL容量。

如前所述,延遲初始化可以通過延遲必須初始化列表的時間(從而選擇其初始大小)來幫助您。

如果由於您的部門政策而不允許使用null初始化對象(我認為沒有什么意義),因此無法進行延遲初始化,則一種變通方法是將一個空列表初始化為

List widget = new ArrayList<>(0)

僅當(且如果)您確實需要使用列表時,才創建一個新的列表對象:

widget = new ArrayList<>(someSize)

並希望那時您可以知道列表可以達到的最大大小(或至少是其數量級)。

我知道,這是一個非常愚蠢的把戲,但它遵循您的政策。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM