ArrayList的使用方法【轉載】
ArrayList 的使用方法 【轉載】
***
Source URL: http://i.yesky.com/bbs/jsp/view.jsp?articleID=889992&forumID=150
***
1 、什么是 ArrayList
ArrayList 就是傳說中的動態數組,用 MSDN 中的說法,就是 Array 的復雜版本,它提供了如下一些好處:
動態的增加和減少元素
實現了 ICollection 和 IList 接口
靈活的設置數組的大小
2 、如何使用 ArrayList
最簡單的例子:
ArrayList List = new ArrayList();
for( int i=0;i<10;i++ ) // 給數組增加 10 個 Int 元素
List.Add(i);
//.. 程序做一些處理
List.RemoveAt(5);// 將第 6 個元素移除
for( int i=0;i<3;i++ ) // 再增加 3 個元素
List.Add(i+20);
Int32[] values = (Int32[])List.ToArray(typeof(Int32));// 返回 ArrayList 包含的數組
這是一個簡單的例子,雖然沒有包含 ArrayList 所有的方法,但是可以反映出 ArrayList 最常用的用法
3 、 ArrayList 重要的方法和屬性
( 1 )構造器
ArrayList 提供了三個構造器:
public ArrayList();
默認的構造器,將會以默認( 16 )的大小來初始化內部的數組
public ArrayList(ICollection);
用一個 ICollection 對象來構造,并將該集合的元素添加到 ArrayList
public ArrayList(int);
用指定的大小來初始化內部的數組
( 2 )IsSynchronized 屬性和 ArrayList.Synchronized 方法
IsSynchronized 屬性指示當前的 ArrayList 實例是否支持線程同步,而 ArrayList.Synchronized 靜態方法則會返回一個 ArrayList 的線程同步的封裝。
如果使用非線程同步的實例,那么在多線程訪問的時候,需要自己手動調用 lock 來保持線程同步,例如:
ArrayList list = new ArrayList();
//...
lock( list.SyncRoot ) // 當 ArrayList 為非線程包裝的時候, SyncRoot 屬性其實就是它自己,但是為了滿足 ICollection 的 SyncRoot 定義,這里還是使用 SyncRoot 來保持源代碼的規范性
{
list.Add( “ Add a Item ” );
}
如果使用 ArrayList.Synchronized 方法返回的實例,那么就不用考慮線程同步的問題,這個實例本身就是線程安全的,實際上 ArrayList 內部實現了一個保證線程同步的內部類, ArrayList.Synchronized 返回的就是這個類的實例,它里面的每個屬性都是用了 lock 關鍵字來保證線程同步。
****
但是,使用這個方法( ArrayList.Synchronized )并不能保證枚舉的同步,例如,一個線程正在刪除或添加集合項,而另一個線程同時進行枚舉,這時枚舉將會拋出異常。所以,在枚舉的時候,你必須明確使用 SyncRoot 鎖定這個集合。
Hashtable 與 ArrayList 關于線程安全性的使用方法類似。
****
( 3 )Count 屬性和 Capacity 屬性
Count 屬性是目前 ArrayList 包含的元素的數量,這個屬性是只讀的。
Capacity 屬性是目前 ArrayList 能夠包含的最大數量,可以手動的設置這個屬性,但是當設置為小于 Count 值的時候會引發一個異常。
( 4 )Add 、 AddRange 、 Remove 、 RemoveAt 、 RemoveRange 、 Insert 、 InsertRange
這幾個方法比較類似
Add 方法用于添加一個元素到當前列表的末尾
AddRange 方法用于添加一批元素到當前列表的末尾
Remove 方法用于刪除一個元素,通過元素本身的引用來刪除
RemoveAt 方法用于刪除一個元素,通過索引值來刪除
RemoveRange 用于刪除一批元素,通過指定開始的索引和刪除的數量來刪除
Insert 用于添加一個元素到指定位置,列表后面的元素依次往后移動
InsertRange 用于從指定位置開始添加一批元素,列表后面的元素依次往后移動
另外,還有幾個類似的方法:
Clear 方法用于清除現有所有的元素
Contains 方法用來查找某個對象在不在列表之中
其他的我就不一一累贅了,大家可以查看 MSDN ,上面講的更仔細
( 5 )TrimSize 方法
這個方法用于將 ArrayList 固定到實際元素的大小,當動態數組元素確定不在添加的時候,可以調用這個方法來釋放空余的內存。
( 6 )ToArray 方法
這個方法把 ArrayList 的元素 Copy 到一個新的數組中。
4 ArrayList 與數組轉換
例 1 :
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = (Int32[])List.ToArray(typeof(Int32));
例 2 :
ArrayList List = new ArrayList();
List.Add(1);
List.Add(2);
List.Add(3);
Int32[] values = new Int32[List.Count];
List.CopyTo(values);
上面介紹了兩種從 ArrayList 轉換到數組的方法
例 3 :
ArrayList List = new ArrayList();
List.Add( “ string ” );
List.Add( 1 );
// 往數組中添加不同類型的元素
object[] values = List.ToArray(typeof(object)); // 正確
string[] values = (string[])List.ToArray(typeof(string)); // 錯誤
和數組不一樣,因為可以轉換為 Object 數組,所以往 ArrayList 里面添加不同類型的元素是不會出錯的,但是當調用 ArrayList 方法的時候,要么傳遞所有元素都可以正確轉型的類型或者 Object 類型,否則將會拋出無法轉型的異常。
5 、ArrayList 最佳使用建議
這一節我們來討論 ArrayList 與數組的差別,以及 ArrayList 的效率問題
( 1 ) ArrayList 是 Array 的復雜版本
ArrayList 內部封裝了一個 Object 類型的數組,從一般的意義來說,它和數組沒有本質的差別,甚至于 ArrayList 的許多方法,如 Index 、 IndexOf 、 Contains 、 Sort 等都是在內部數組的基礎上直接調用 Array 的對應方法。
( 2 )內部的 Object 類型的影響
對于一般的引用類型來說,這部分的影響不是很大,但是對于值類型來說,往 ArrayList 里面添加和修改元素,都會引起裝箱和拆箱的操作,頻繁的操作可能會影響一部分效率。
但是恰恰對于大多數人,多數的應用都是使用值類型的數組。
消除這個影響是沒有辦法的,除非你不用它,否則就要承擔一部分的效率損失,不過這部分的損失不會很大。
( 3 )數組擴容
這是對 ArrayList 效率影響比較大的一個因素。
每當執行 Add 、 AddRange 、 Insert 、 InsertRange 等添加元素的方法,都會檢查內部數組的容量是否不夠了,如果是,它就會以當前容量的兩倍來重新構建一個數組,將舊元素 Copy 到新數組中,然后丟棄舊數組,在這個臨界點的擴容操作,應該來說是比較影響效率的。
例 1 :比如,一個可能有 200 個元素的數據動態添加到一個以默認 16 個元素大小創建的 ArrayList 中,將會經過:
16*2*2*2*2 = 256
四次的擴容才會滿足最終的要求,那么如果一開始就以:
ArrayList List = new ArrayList( 210 );
的方式創建 ArrayList ,不僅會減少 4 次數組創建和 Copy 的操作,還會減少內存使用。
例 2 :預計有 30 個元素而創建了一個 ArrayList :
ArrayList List = new ArrayList(30);
在執行過程中,加入了 31 個元素,那么數組會擴充到 60 個元素的大小,而這時候不會有新的元素再增加進來,而且有沒有調用 TrimSize 方法,那么就有 1 次擴容的操作,并且浪費了 29 個元素大小的空間。如果這時候,用:
ArrayList List = new ArrayList(40);
那么一切都解決了。
所以說,正確的預估可能的元素,并且在適當的時候調用 TrimSize 方法是提高 ArrayList 使用效率的重要途徑。
( 4 )頻繁的調用 IndexOf 、 Contains 等方法( Sort 、 BinarySearch 等方法經過優化,不在此列)引起的效率損失
首先,我們要明確一點, ArrayList 是動態數組,它不包括通過 Key 或者 Value 快速訪問的算法,所以實際上調用 IndexOf 、 Contains 等方法是執行的簡單的循環來查找元素,所以頻繁的調用此類方法并不比你自己寫循環并且稍作優化來的快,如果有這方面的要求,建議使用 Hashtable 或 SortedList 等鍵值對的集合。
ArrayList al=new ArrayList();
al.Add("How");
al.Add("are");
al.Add("you!");
al.Add(100);
al.Add(200);
al.Add(300);
al.Add(1.2);
al.Add(22.8);
.........
// 第一種遍歷 ArrayList 對象的方法
foreach(object o in al)
{
Console.Write(o.ToString()+" ");
}
// 第二種遍歷 ArrayList 對象的方法
IEnumerator ie=al.GetEnumerator();
while(ie.MoveNext())
{
Console.Write(ie.Curret.ToString()+" ");
}
// 第三種遍歷 ArrayList 對象的方法
我忘記了 , 好象是 利用 ArrayList 對象的一個屬性 , 它返回一此對象中的元素個數 .
然后在利用索引
for(int i=0;i<Count;i++)
{
Console.Write(al[i].ToString()+" ");
}
-------------------------數組的用法----------------------------------------------
數組概述
C# 數組從零開始建立索引,即數組索引從零開始。 C# 中數組的工作方式與在大多數其他流行語言中的工作方式類似。但還有一些差異應引起注意。
聲明數組時,方括號 ([]) 必須跟在類型后面,而不是標識符后面。在 C# 中,將方括號放在標識符后是不合法的語法。
int[] table; // not int table[];
另一細節是,數組的大小不是其類型的一部分,而在 C 語言中它卻是數組類型的一部分。這使您可以聲明一個數組并向它分配 int 對象的任意數組,而不管數組長度如何。
int[] numbers; // declare numbers as an int array of any size
numbers = new int[10]; // numbers is a 10-element array
numbers = new int[20]; // now it's a 20-element array
聲明數組
C# 支持一維數組、多維數組(矩形數組)和數組的數組(交錯的數組)。下面的示例展示如何聲明不同類型的數組:
一維數組:
int[] numbers;
多維數組:
string[,] names;
數組的數組(交錯的):
byte[][] scores;
聲明數組(如上所示)并不實際創建它們。在 C# 中,數組是對象(本教程稍后討論),必須進行實例化。下面的示例展示如何創建數組:
一維數組:
int[] numbers = new int[5];
多維數組:
string[,] names = new string[5,4];
數組的數組(交錯的):
byte[][] scores = new byte[5][];
for (int x = 0; x < scores.Length; x++)
{
scores[x] = new byte[4];
}
還可以有更大的數組。例如,可以有三維的矩形數組:
int[,,] buttons = new int[4,5,3];
甚至可以將矩形數組和交錯數組混合使用。例如,下面的代碼聲明了類型為 int的二維數組的三維數組的一維數組。
int[][,,][,] numbers;
初始化數組
C# 通過將初始值括在大括號 ({}) 內為在聲明時初始化數組提供了簡單而直接了當的方法。下面的示例展示初始化不同類型的數組的各種方法。
注意 如果在聲明時沒有初始化數組,則數組成員將自動初始化為該數組類型的默認初始值。另外,如果將數組聲明為某類型的字段,則當實例化該類型時它將被設置為默認值 null。
一維數組
int[] numbers = new int[5] {1, 2, 3, 4, 5};
string[] names = new string[3] {"Matt", "Joanne", "Robert"};
可省略數組的大小,如下所示:
int[] numbers = new int[] {1, 2, 3, 4, 5};
string[] names = new string[] {"Matt", "Joanne", "Robert"};
如果提供了初始值設定項,則還可以省略 new運算符,如下所示:
int[] numbers = {1, 2, 3, 4, 5};
string[] names = {"Matt", "Joanne", "Robert"};
多維數組
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };
可省略數組的大小,如下所示:
int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} };
如果提供了初始值設定項,則還可以省略 new運算符,如下所示:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = { {"Mike", "Amy"}, {"Mary", "Albert"} };
交錯的數組(數組的數組)
可以像下例所示那樣初始化交錯的數組:
int[][] numbers = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
可省略第一個數組的大小,如下所示:
int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
-或-
int[][] numbers = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
請注意,對于交錯數組的元素沒有初始化語法。
訪問數組成員
訪問數組成員可以直接進行,類似于在 C/C++ 中訪問數組成員。例如,下面的代碼創建一個名為 numbers的數組,然后向該數組的第五個元素賦以 5:
int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
numbers[4] = 5;
下面的代碼聲明一個多維數組,并向位于 [1, 1]的成員賦以 5:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} };
numbers[1, 1] = 5;
下面聲明一個一維交錯數組,它包含兩個元素。第一個元素是兩個整數的數組,第二個元素是三個整數的數組:
int[][] numbers = new int[][] { new int[] {1, 2}, new int[] {3, 4, 5}};
下面的語句向第一個數組的第一個元素賦以 58,向第二個數組的第二個元素賦以 667:
numbers[0][0] = 58;
numbers[1][1] = 667;
數組是對象
在 C# 中,數組實際上是對象 。System.Array是所有數組類型的抽象基類型。可以使用 System.Array具有的屬性以及其他類成員。這種用法的一個示例是使用“長度”(Length)屬性獲取數組的長度。下面的代碼將 numbers數組的長度(為 5)賦給名為 LengthOfNumbers的變量:
int[] numbers = {1, 2, 3, 4, 5};
int LengthOfNumbers = numbers.Length;
System.Array 類提供許多有用的其他方法/屬性,如用于排序、搜索和復制數組的方法。
對數組使用 foreach
C# 還提供 foreach語句。該語句提供一種簡單、明了的方法來循環訪問數組的元素。例如,下面的代碼創建一個名為 numbers的數組,并用 foreach語句循環訪問該數組:
int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0};
foreach (int i in numbers)
{
System.Console.WriteLine(i);
}
由于有了多維數組,可以使用相同方法來循環訪問元素,例如:
int[,] numbers = new int[3, 2] {{9, 99}, {3, 33}, {5, 55}};
foreach(int i in numbers)
{ Console.Write("{0} ", i);}
該示例的輸出為:
9 99 3 33 5 55
不過,由于有了多維數組,使用嵌套 for循環將使您可以更好地控制數組元素。
posted on 2006-03-06 17:21 夢在天涯 閱讀(4497) 評論(1) 編輯 收藏 引用 所屬分類: C#/.NET