[英]List<T> and ArrayList default capacity
我一直在用Reflector查看.NET的List和ArrayList實現。
當看到Add(T項目)時,我碰到了這個。 EnsureCapacity (this._size + 1):
public void Add(T item)
{
if (this._size == this._items.Length)
{
this.EnsureCapacity(this._size + 1);
}
this._items[this._size++] = item;
this._version++;
}
所以EnsureCapacity看起來像這樣:
private void EnsureCapacity(int min)
{
if (this._items.Length < min)
{
int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
if (num < min)
{
num = min;
}
this.Capacity = num;
}
}
為什么內部容量默認為4,然后以2的倍數遞增(即:double)?
關於在需要調整大小時加倍,原因如下。 假設您要將n
項目插入List
。 我們將重新調整列表的大小不超過log n
次。 因此,將n
項插入List
中將花費最壞情況O(n)
時間,因此插入在分攤的時間內是恆定的。 此外,浪費的空間量高於n
。 任何恆定比例增長的策略都將導致不變的攤銷插入時間和線性浪費空間。 比恆定比例增長更快的速度可以導致更快的插入,但代價是浪費更多的空間。 比恆定比例增長慢的生長可以減少浪費的空間,但代價是插入速度較慢。
默認容量是浪費很少的內存(並且從小時開始沒有什么害處,因為從我們剛剛看到的時間/空間角度看,雙倍調整大小的策略是好的)。
4是一個很好的默認值,因為大多數集合中只有幾個項目。 增量完成是為了確保每次添加項目時都不進行內存分配。
請參閱Joel關於內存使用情況的這篇好文章以及為什么分配雙倍所需內容是一個好主意。
http://www.joelonsoftware.com/printerFriendly/articles/fog0000000319.html
這是相關的引用:
假設您編寫了一個智能strcat函數,可以自動重新分配目標緩沖區。 它應該始終將其重新分配到所需的確切大小嗎? 我的老師和導師Stan Eisenstat建議,當你調用realloc時,你應該總是將以前分配的內存大小加倍。 這意味着你永遠不必再調用realloc超過lg n次,即使對於巨大的字符串也具有良好的性能特征,並且你永遠不會浪費超過50%的內存。
順便說一句,列表<>和字典<>現在默認為10,但我敢打賭它們具有相同的遞增邏輯。
我敢打賭,這樣你就可以創建沒有多次分配的小型列表。 尺寸加倍是為了簡單而不是具有復雜的縮放算法。
似乎4是一個合理的權衡,大到足以容納有4個項目或更少的頻繁情況,並沒有太多浪費的項目。
每個分配增加的容量增加一倍,確保它可以容納容器中已有項目數量的兩倍。 這是與C ++的向量容器類似的算法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.