2

潜在的に巨大な (数百万のアイテム) データセット (ディスクに保存されている) をループし、List<T>. リストにアイテムを追加するときは、他のスレッドがリストにアクセスしているため、そのアイテムをロックします。

私は2つの可能な実装のどちらかを決定しようとしています:

1) 項目を追加する必要があるたびにリストをロックします。

2) 項目を見つけたら追加する一時リストを使用List<T>.AddRange()し、そのリストに項目をチャンクで追加するために使用します (たとえば、1000 件の一致が見つかった場合)。これにより、リストのロックを要求する頻度が少なくなりますが、AddRange() が新しいアイテムを正確に収容するのに十分なだけ容量を増やす場合、リストのサイズが何度も変更されることになります。

私の質問は次のとおりです。私が理解しているように、アイテムを一度に 1 つずつ追加すると、List<T>容量に達するたびに a の内部容量が 2 倍になりますが、どのようList<T>.AddRange()に動作するかはわかりません。新しいアイテムを収容するのに十分な容量が追加されるだけだと思いますが、これを確認する方法が見つかりません. MSDN での容量の増加方法の説明は、Add() と AddRange() でほぼ同じですが、AddRange の場合、新しいカウントが容量よりも大きい場合は、カウントが既に最大値になっている場合ではなく、容量が増加するという点が異なります。容量と同じ。
私には、AddRange() を使用して現在の容量を超えるのに十分な項目を追加すると、Add() を使用して現在の容量を超えるのと同じ方法で容量が増加するように見えます。

では、現在の容量を超えるのに十分な大きさのチャンクを使用してアイテムを追加するとList<T>.AddRange()、新しいアイテムを収容するのに十分な容量しか増加しませんか、それとも容量が 2 倍になりますか? それとも、私が考えもしなかった何か他のことをしますか?

実装方法に関する一般的な質問であるため、コードサンプルがなくても十分に明確であることを願っていますList<T>が、そうでない場合は、質問をより明確にするために追加します。前述のように、MSDN のドキュメントを読みましたが、明確な答えが見つかりませんでした。ここでも同様の質問を検索しましたが、何も見つかりませんでしたが、見逃したものがあれば教えてください。

4

3 に答える 3

7

AddRangeパラメーターとして渡されたコレクションが実装している限りICollection<T>、配列サイズは 1 回だけインクリメントされます。

ICollection<T> collection2 = collection as ICollection<T>;
if (collection2 != null)
{
    int count = collection2.Count;
    if (count > 0)
    {
        this.EnsureCapacity(this._size + count);

    // (...)

それ以外の場合は、各要素の標準の列挙とInsertメソッド呼び出しが行われます。

}
else
{
    using (IEnumerator<T> enumerator = collection.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            this.Insert(index++, enumerator.Current);
        }
    }
}

編集

メソッドを調べEnsureCapacityます:

private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num > 2146435071)
        {
            num = 2146435071;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}

配列サイズを だけ増やします。また、呼び出し後の最終的な配列サイズで呼び出されるMax(old_size * 2, min)ため、メソッドを使用して追加されるコレクションの現在のサイズとサイズに注意が必要です。min = old_size + countAddRangeMax(old_size * 2, old_size + count)List<T>AddRange

于 2013-09-02T12:21:19.683 に答える
3

と同様に容量を増やしAddます。これはドキュメントでは明示的に言及されていませんが、ソース コードを見ると、AddAddRange内部でEnsureCapacity.

于 2013-09-02T12:23:54.383 に答える