淺談 ArrayList 內部原理


System.Collections.ArrayList 就是我們常說的動態數組,也是我們常用的 "數據類型" 之一。
在 MSDN 上是這樣表述的:使用大小可按需動態增加的數組實現 IList 接口。
我來解釋一下,就是:一個可以根據需要動態增加使用大小並可按照索引單獨訪問的對象的非泛型集合。
一般人都認為 ArrayList 就是一個 "純動態" 的數組,與 <數據結構> 中 "鏈表" 的原理一樣。
在對 ArrayList 做深入探究和學習之前,我也是這么認為的。可是,事實並非如此。

在 ArrayList 內部有一個 Object 類型的數組,當第一次添加元素的時候,將其初始化並把容量設置為 4。
如果,當前的數組還有剩余空間的話,那我們就可以直接將元素添加到相應的位置。
否則,當數組空間已經用完時,.NET 運行庫會創建一個新的數組,數組的空間是原來的兩倍,並將原有數組中的元素拷貝到新數組中。
最后,將新數組的地址賦給老數組的變量。

我們來看下面一段代碼:

  1     public class ArrayList
2 {
3 /// <summary>
4         /// 默認容量
5        /// </summary>
6 private const int defaultCapacity = 4;
7
8 /// <summary>
9         /// 當前數組中元素的數量
10         /// </summary>
11 private int size;
12
13 /// <summary>
14         /// 用於存放元素的數組
15         /// </summary>
16 private object[] items;
17
18 /// <summary>
19         /// 用於初始化 items 的靜態只讀 Object 類型數組
20         /// </summary>
21 private static readonly object[] emptyArray;
22
23 /// <summary>
24         /// 當前的最大容量
25         /// </summary>
26 public int Capacity
27 {
28 get
29 {
30 //返回當前數組的長度
31 return this.items.Length;
32 }
33 set
34 {
35 //設置的值不等於當前 items 數組的長度
36 if (value != this.items.Length)
37 {
38 if (value > 0)
39 {
40 //以設置的值為長度聲明一個新的 Object 類型的數組
41 object[] destinationArray = new object[value];
42
43 if (this.size > 0)
44 {
45 //並將 items 數組中的元素拷貝到 destinationArray 數組中
46 Array.Copy(this.items, 0, destinationArray, 0, this.size);
47 }
48
49 //再將 destinationArray 賦給 items 數組
50 this.items = destinationArray;
51 }
52 else
53 {
54 this.items = new object[4];
55 }
56 }
57
58 }
59 }
60
61 /// <summary>
62        /// 靜態構造函數
63         /// 把 emptyArray 初始化為一個容量為 0 的 Object 類型的數組。
64         /// </summary>
65 static ArrayList()
66 {
67 emptyArray = new object[0];
68 }
69
70 /// <summary>
71         /// 無參構造函數
72         /// 將 emptyArray 數組的值賦給 items 數組;
73         /// 也就是將 items 初始化一個容量為 0 的 Object 類型的數組。
74         /// </summary>
75 public ArrayList()
76 {
77 this.items = emptyArray;
78 }
79
80 /// <summary>
81         /// 增加元素的方法
82         /// </summary>
83         /// <param name="value">傳入的對象</param>
84         /// <returns>當前添加元素的索引</returns>
85 public int Add(object value)
86 {
87 //如果當前數組中元素的數量等於 items 數組的長度的話
88 if (this.size == this.items.Length)
89 {
90 EnsureCapacity(this.size + 1);
91 }
92 //將傳入進來的元素添加到 items 數組中
93 this.items[this.size] = value;
94 //返回當前元素在 items 數組中的索引
95 return this.size++;
96 }
97
98 /// <summary>
99         /// 確保滿足容量
100         /// </summary>
101         /// <param name="min"></param>
102 private void EnsureCapacity(int min)
103 {
104 if (this.items.Length < min)
105 {
106 //如果當前的存放元素數組的長度等於0的話,num 就等於 4,否則 num 等於當前元素數組長度的兩倍
107 int num = (this.items.Length == 0) ? 4 : (this.items.Length * 2);
108 if (num < min)
109 {
110 num = min;
111 }
112 //將當前的最大容量設置為 num
113 this.Capacity = num;
114 }
115 }
116 }

這段代碼是我從 ArrayList 類的內部代碼中抽離出來的一小部分,里面有詳細的注釋,我就不多說了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM