[英]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參數構造函數,則它保證必須調整其使用的每個大小。
這是性能優化的三個定律
如果您仍然以某種方式仍然相信自己對編譯器有所了解,請檢查以下問題: 為什么處理排序數組比未排序數組更快?
如果列表不總是使用,請使用延遲初始化
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.