.NETデータ構造:
ArrayListとListが実際に異なる理由についての詳細
配列
あるユーザーが言うように、配列は「古い学校」のコレクションです(はい、配列はの一部ではありませんが、コレクションと見なされますSystem.Collections
)。しかし、他のコレクション、つまりタイトルにリストしたもの(ここでは、ArrayListおよびList(Of T))と比較して、配列について「古い」とは何ですか?配列を見て、基本から始めましょう。
まず、Microsoft .NETの配列は、「いくつかの[論理的に関連する]アイテムを単一のコレクションとして扱うことができるメカニズム」です(リンクされた記事を参照)。どういう意味ですか?配列は、個々のメンバー(要素)を順番に、開始アドレスとともにメモリに順番に格納します。配列を使用することで、そのアドレスから始まる順次格納された要素に簡単にアクセスできます。
それ以上に、101の一般的な概念のプログラミングに反して、配列は実際には非常に複雑になる可能性があります。
配列は、1次元、多次元、またはjaddedにすることができます(ジャグ配列は読む価値があります)。配列自体は、動的ではありません:初期化されたら、の配列のnサイズの埋蔵保持するのに十分なスペースn個のオブジェクトの数。配列内の要素数は増減できません。Dim _array As Int32() = New Int32(100)
配列が100個のInt32プリミティブ型オブジェクトを含むために、メモリブロックに十分なスペースを予約します(この場合、配列は0を含むように初期化されます)。このブロックのアドレスがに返され_array
ます。
記事によると、共通言語仕様(CLS)では、すべての配列がゼロベースである必要があります。.NETの配列は、ゼロベースでない配列をサポートしています。ただし、これはあまり一般的ではありません。ゼロベースの配列の「共通性」の結果として、マイクロソフトはそのパフォーマンスの最適化に多くの時間を費やしてきました。したがって、SZにはそれらを操作するための特定の中間言語命令があるため、1次元のゼロベースの(SZ)配列は「特別」であり、(多次元などではなく)本当に配列の最良の実装です。
配列は常に参照によって(メモリアドレスとして)渡されます。これは配列パズルの重要な部分です。境界チェックは実行されますが(エラーがスローされます)、配列の境界チェックを無効にすることもできます。
繰り返しになりますが、配列の最大の障害は、配列のサイズを変更できないことです。それらには「固定」容量があります。ArrayListとList(Of T)の歴史を紹介します。
ArrayList-一般的でないリスト
ArrayList(およびList(Of T)
-いくつかの重要な違いがありますが、ここで、後で説明します)は、(広義の)コレクションへの次の追加としておそらく最もよく考えられています。ArrayListはIList( 'ICollection'の子孫)インターフェイスを継承します。ArrayListは、それ自身であり、かさばるより必要- オーバーヘッド -リストより。
IList
実装は、ArrayListを固定サイズのリスト(配列のような)として扱うことができます。ただし、ArrayListsによって追加された追加の機能を超えて、この場合のArrayLists(Arraysより)は著しく遅いため、固定サイズのArrayListsを使用する利点はありません。
私が読んだところ、ArrayListsをギザギザにすることはできません。「要素としての多次元配列の使用はサポートされていません」。ここでも、ArrayListsの棺の中にある別の釘。ArrayListも「型付け」されていません。つまり、すべての下で、ArrayListはオブジェクトの動的な配列ですObject[]
。これには、ArrayListを実装するときに多くのボックス化(暗黙的)とボックス化解除(明示的)が必要になり、オーバーヘッドが増加します。
根拠のない考え:私は、ArrayListsが配列からリスト型のコレクションに移動しようとする試みの一種の粗野な概念の子であることを教授の1人から読んだり聞いたりしたことを覚えていると思います。コレクションに関してさらなる開発が行われたため、これらはもはや最良のオプションではありません
List(Of T):ArrayListがどのようになったか
メモリ使用量の違いは、List(Of Int32)が同じプリミティブ型を含むArrayListよりも56%少ないメモリを消費するほど十分に重要です(上記の紳士のリンクされたデモでは、8 MB対19 MB:ここでもリンクされています)。これは、64ビットマシンによって複合された結果です。この違いは、実際には2つのことを示しています。1つ目は、(1)ボックス化されたInt32タイプの「オブジェクト」(ArrayList)は、純粋なInt32プリミティブタイプ(List)よりもはるかに大きいことです。2番目(2)、64ビットマシンの内部動作の結果として、差は指数関数的です。
それで、違いは何ですか?そしてList(Of T)は何ですか?MSDNはList(Of T)
、「...インデックスでアクセスできるオブジェクトの強く型付けされたリスト」と定義しています。ここで重要なのは、「強く型付けされた」ビットです。List(Of T)は型を「認識」し、オブジェクトをその型として格納します。したがって、Int32
は型Int32
ではなくとして格納されObject
ます。これにより、ボックス化とボックス化解除によって発生する問題が解消されます。
MSDNでは、この違いはプリミティブ型を格納するときにのみ影響し、参照型を格納しないと規定しています。また、違いは実際には500を超える要素という大きなスケールで発生します。さらに興味深いのは、MSDNのドキュメントに、「ArrayListクラスを使用する代わりに、List(Of T)クラスの型固有の実装を使用するほうが有利だ」と書かれていることです。
基本的に、List(Of T)はArrayListですが、より優れています。これは、ArrayListの「一般的な同等物」です。ArrayListと同様に、ソートされるまでは、ソートされることが保証されていません(図に移動)。List(Of T)にもいくつかの機能が追加されています。