.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>のほうが短くなるということです。

