4

Class1 の一般的なリストがあり、通常、特定のセッションに対して約 100 個のオブジェクトがあるとします。リストに特定のオブジェクトがあるかどうかを確認したいと思います。ASP.NET 2.0 では、これを行うことができます。

Dim objResult as Class1 = objList.Find(objSearch)

パフォーマンスの観点から見て、従来の For ループと比較した場合、このアプローチはどのように評価されますか?

リストの長さが増減すると、これはどのように変化しますか?

4

2 に答える 2

7

これはループとまったく同じです。それが内部で行われていることです。

リストがソートされていて、特定の値を探している場合は、代わりに使用できる可能性がありますが、考えみるBinarySearchと、述語やデータの順序について何も知らない場合は、調べなければなりません一致が見つかるまで各アイテム。たまたま、リストの最初の項目を返すように指定されているため、明らかな順序で検索します。Find

これは、リストのサイズに比例します。つまり、平均して、10 倍のサイズのリストを検索すると、10 倍の時間がかかります。もちろん、一致が見つかるかどうか、どこで見つかるかによって異なります。すべてのケースで最初の項目が一致する場合、リストがどれほど大きくても同時に終了します:)

正直なところ、オブジェクトが 100 個しかないので、ボトルネックになる可能性はほとんどないように思えます。

于 2010-05-01T17:24:13.127 に答える
3

.Net がReflector を使用してメソッドをList実装する方法を簡単に確認できます。Find

Public Function Find(ByVal match As Predicate(Of T)) As T
    If (match Is Nothing) Then
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match)
    End If
    Dim i As Integer
    For i = 0 To Me._size - 1
        If match.Invoke(Me._items(i)) Then
            Return Me._items(i)
        End If
    Next i
    Return CType(Nothing, T)
End Function

両方の実装の唯一の違いは、このロジックをループ内にインライン化Findする代わりに への呼び出しが必要なことです。match

興味深いことに、この単純なパフォーマンス:

var persons = new List<Person>();
for (int i = 0; i < 100; i++)
{
    persons.Add(new Person { ID = i });
}

GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    persons.Find(person => person.ID == i % 100);

}
sw.Stop();
Console.WriteLine(sw.Elapsed);

GC.Collect();
sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    for (int j = 0; j < 100; j++)
    {
        if (persons[j].ID == i % 100)
        {
            break;
        }
    }
}
sw.Stop();
Console.WriteLine(sw.Elapsed);

Find
を使用してリストをクエリするのに必要な合計時間は05.7990078秒です。ループ を使用してリストを照会するのに必要な合計時間は 06.3551074秒です。

この結果は、いくつかの実行で一貫しているようです。

編集- の利点の説明が見つかりましたFind:
Findは、各反復で基になる配列に直接アクセスするため、より高速に動作します。ループはListインデクサーを介してアクセスします。これには、アクセスごとにインデックスの検証が必要です。

Public Default Property Item(ByVal index As Integer) As T
    Get
        If (index >= Me._size) Then
            ThrowHelper.ThrowArgumentOutOfRangeException
        End If
        Return Me._items(index) // _items is the underlying array.
    End Get
于 2010-05-01T17:24:18.083 に答える