2011-12-15 7 views
1

私のコードでは、オブジェクトの大きなコレクションを作成する必要があることがあります。後でアイテムを追加する必要があるかもしれないので、コレクションではなく配列が必要であることに注意してください。大量のアイテムを含むリスト<MyObject>の効率的な作成

効率的な方法は何ですか?

オブジェクトは非常に単純で、デフォルトのパラメータレスコンストラクタで高速に作成できるとしましょう。このような何か:

class MyObject 
{ 
    private int a; 

    public int A 
    { 
     get { return a; } 
     set { a = value; } 
    } 
} 

確かに、私はこのような私のコレクションを作成することができます。

List<MyObject> list = new List<MyObject>(knownNumberOfItems); 
for (int i = 0; i < knownNumberOfItems; i++) 
    list.Add(new MyObject()); 

しかし、おそらく同じことを行うには良い方法はありますか?議論から

概要:

  • 参照型のためにこれを行うにはより高速な方法はありません。値の型を使用すると、パフォーマンスが向上する場合があります。
  • 新しいアイテムが後で追加されたときに、再割り当ての数を減らすために、最初により多くの領域を割り当てるようにしてください。
+0

要件に合っている場合は、MyObjectを構造体にすることを検討してください。それはいくらかのオーバーヘッドを削ってしまうでしょう – Polity

+0

FYI、List は配列によって裏付けられています。パフォーマンス上の懸念から、アレイを使用したくないと述べています。配列を配列の代わりに使用しても、リストは順番に配列自体を使用するため、この問題は軽減されません。 – Dejas

+0

@Dejas私は基本配列の再割り当てについては何もできないと思います。しかし、私はちょうどこれらの再配分を自分でやりたくはありません。 – Bobrovsky

答えて

2

私がよく知っている方法はありません。私は個人的にはforループのボディの周りにカッコを使用しますが、新しいオブジェクトへの別個の参照が設定された、指定されたサイズのリストを作成する方法として、それについてです。重要な点は、最初にリストのサイズを指定したことです。したがって、Addコールでは、内部的に何かを再割り当てする必要はありません。

後でアイテムを追加する可能性がある場合は、になるかもしれません。は少し大きめにしたいと思っています。

これはシステムのボトルネックではありません。いつものように、可読性が主な関心事であり(私が示唆した変更以外はここで問題にはなりません)測定によって懸念が検証された場合にのみ、低レベルで変化を引き起こす。

+0

私は、配列を使わないことについての彼の指摘は、今はknown_number_of_itemsが必要だと知っていますが、未知数のオブジェクトを将来追加する必要があるということです。 – Dejas

+0

@Dejas:はい、しかし、彼は "追加する余分なアイテム"の可能性のある分布に関する*いくつかの考えを持っているかもしれません。したがって、たとえば、いくつかの追加を期待して追加の10%を追加する価値があります。 –

+0

私はラクダ用ケーシングも使用しています。アンダースコアは、コードスニペットで重視するためにのみ使用されます。 – Bobrovsky

1

.Net 2.0にはありません。 .Net 3.5からは少し短く書くことができますが、コンパイルされた結果は基本的に同じになります。

1

あなたの方法は非常に効率的です - 配列はすべてのアイテムに十分なスペースで作成され、list.Addは非常に高速です。

パフォーマンスに問題がありますか?私は

LinkedList<T> list = ... 

を見て検討するかもしれない

+0

はい、私は大規模なコレクション(> 10000アイテム)でいくつかの問題が発生します。 – Bobrovsky

+0

@Bobrovskyどのような問題がありますか?どんなコードがゆっくりと実行されるようですか?プロファイリングしましたか? – phoog

+0

@phoogはい、私はプロフィールをしました。私のコードにはいくつかの問題があります。私は1つの質問でそれらのすべてを議論したくありません。この質問のために、大規模なコレクションの作成をスピードアップできるかどうかを知りたかっただけです。私はいくつか貴重なアドバイスを受けると思います。 – Bobrovsky

1

はリンクリストにオペレーションを追加し、一定の時間です。

+0

List <>が事前に割り当てられている場合(その場合のように)、アイテムの追加は一定の時間内に行われ、定数はLinkedListの値よりも小さくなります。トラバーサルも効率的です。すべての実用的な目的のために、彼はここで配列を使用しています。 – zmbq

+1

@Dejas:リストのサイズをあらかじめ知っているならば、サイズとともに初期化された 'List 'は、加算演算のための一定時間です。彼の例では、彼は既にサイズを知っていた。 –

+0

ありがとうございましたが、インデックスにアクセスできるようにコレクション内のアイテムが必要です。 – Bobrovsky

1

タイプに値タイプ(struct)を作成して、インスタンスにメモリを割り当てる必要がなく、リストがメモリを断片化しないようにすることを検討してください。 O(n)で実行するように、そのdocumentationから、その保証を

var List = new MyList<MyObject>(Enumerable<MyObject>.Repeat(new MyObject(), 
           known_number_of_items)); 

:その後のようなリストを作成します。ただし、同じオブジェクトを繰り返し挿入するため、参照型(class)では機能しません。

+0

提案していただきありがとうございますが、私の場合、型は値型にすることはできません。 – Bobrovsky

+0

@Bobrovsky:C#でオブジェクトの連続した展開可能なストレージを作成する方法はありません。私は、C++では1つの連続した拡張可能なコンテナ(std ::)を使用することができますが、膨大な量のオブジェクトを1つずつ作成するとマネージメモリとガベージコレクタに負荷がかかるため、ベクター) – Dani

関連する問題