.NET Frameworkに’ArrayList’と呼ばれるクラスがあります。
このクラスは「動的配列」と呼ばれ、要素を追加したり削除したりと操作が簡単にできるクラスです。
名前空間までつけると’System.Collections.ArrayList’クラスです。
とにかくArrayListを使ってみる
int count = 10000; System.Collections.ArrayList lst = new System.Collections.ArrayList(count); for(int i = 0; i < lst.Capacity; i++) { // 要素に値を追加する lst.Add(i); } for(int i = 0; i < lst.Capacity; i++) { // 値をリストから取り出す int a = (int)lst[i]; }
普通に使えます。
ただ、C++をやっている人はお気づきだと思いますが、「動的配列」なのにあるものがありません。
「格納するデータの型の指定」がないんです。
ArrayListに格納するデータの型は何?
答えは、object型です。
.NET Framework(C#)においては、すべての型はobject型の派生クラスになります。
これによりArrayListクラスというクラスが実現されています。
ところが、.NET Frameworkにはとても似たクラスがあります。
System.Collections.Generic.Listクラスです。
本当は System.Collections.Generic.List<T> (Tは格納するデータの型)と記述して使います。
(C++をやっている人にはこちらのほうがなじみやすいと思います)
同じ処理をSystem.Collections.Generic.Listで書いてみる
さきほどのソースと同じ処理を行うものをSystem.Collections.Generic.Listで書いたものです。
int count = 10000; System.Collections.Generic.List<int> lst = new System.Collections.Generic.List<int>(count); for(int i = 0; i < lst.Capacity; i++) { // 要素に値を追加する lst.Add(i); } for(int i = 0; i < lst.Capacity; i++) { // 値をリストから取り出す int a = (int)lst[i]; }
コードでの違いは1行です。
ここまで見るとint型と格納するデータの型を決めて格納することしかできない’System.Collections.Generic.List<int>’クラスと
なんでも格納できる’System.Collections.ArrayList’クラス、ここだけ見ると「どっちでも・・・」と
思うかもしれませんが、この2つのクラスは動かしてみると処理時間が全く異なります。
ArrayListとList<int>で処理時間を計測してみる
下記のコードで処理時間を計測してみました。
static void Main(string[] args) { int count = 10000; Stopwatch sw = new Stopwatch(); // // ArrayListで処理時間を計測する // System.Collections.ArrayList lst1 = new System.Collections.ArrayList(count); sw.Start(); for(int i = 0; i < lst1.Capacity; i++) { // 要素に値を追加する lst1.Add(i); } sw.Stop(); Console.WriteLine(string.Format("ArrayList set Ticks:{0}", sw.ElapsedTicks)); sw.Reset(); sw.Start(); for (int i = 0; i < lst1.Capacity; i++) { // 値をリストから取り出す int a = (int)lst1[i]; } sw.Stop(); Console.WriteLine(string.Format("ArrayList get Ticks:{0}", sw.ElapsedTicks)); // // List<int>で処理時間を計測する // System.Collections.Generic.List<int> lst2 = new System.Collections.Generic.List<int>(count); sw.Start(); for (int i = 0; i < lst2.Capacity; i++) { // 要素に値を追加する lst2.Add(i); } sw.Stop(); Console.WriteLine(string.Format("List<int> set Ticks:{0}", sw.ElapsedTicks)); sw.Reset(); sw.Start(); for (int i = 0; i < lst2.Capacity; i++) { // 値をリストから取り出す int a = (int)lst2[i]; } sw.Stop(); Console.WriteLine(string.Format("List<int> get Ticks:{0}", sw.ElapsedTicks)); Console.ReadKey(); }
計測した結果です。
ArrayList | List<int> | 差 | |
追加 | 1148 | 592 | -556(List<int>のほうが速い) |
取得 | 305 | 260 | -45(List<int>のほうが速い) |
※計測時の単位はTicks(CPUのカウント数)です。値が小さいほうが速いです。
けっこうな差が出ています。
理由は、System.Collections.ArrayListは
追加するときに、int型のオブジェクトをobject型にしてからリストに登録
取得するときに、object型のオブジェクトをリストから取り出してint型で取得
という動きをしています。
これに対して、System.Collections.Generic.List<int>は
追加するときに、int型のオブジェクトを登録
取得するときに、int型で取得
という動きなので、処理時間はSystem.Collections.Generic.List<int>のほうが短くなるということです。