2012-04-13 7 views
11

Ich schreibe oft Code wie folgt:Wie schnell sind Anzahl und Kapazität?

if (list.Count > 0) { } 

Ist das leistungsfähig? Ist dieser Vorgang wie folgt aussehen:

  • Iterate durch die Liste und zählen seine Elemente
  • Ergebnis: 986.000 Elemente
  • Ist 986.000 größer als 0?
  • return true

Oder wie folgt aus:

  • Abrufen der gespeicherten Anzahl von Elementen in der Liste (986.000)
  • Ist 986.000 größer als 0?
  • return true

Das heißt, die Anzahl der Elemente in der Liste zu bekommen, machen Sie den ganzen Weg durch die Liste zu zählen haben, oder die Anzahl der Elemente irgendwo aufgezeichnet? Und ist das der Fall für alle Klassen ICollection?

Was ist mit der Capacity der Liste?

Antwort

33

Ich schreibe oft Code wie folgt: if (list.Count > 0) { } Ist das effizient?

Ja. Das ruft die Zählung in der Liste ab, die in einem Feld innerhalb der Liste gespeichert ist, und vergleicht es mit Null.

Jetzt eine Frage, die Sie nicht fragen:

Was if (sequence.Count() > 0) { }? (Beachten Sie die Klammern auf Count().)

Wir befragen die Sequenz zur Laufzeit zu sehen, ob es sich um eine Liste, die eine Count Eigenschaft hat, die effizient berechnet werden kann. Wenn es so ist, nennen wir es. Wenn nicht, zählen wir die gesamte Sequenz jeweils ein Element und vergleichen das dann mit Null.

Ist das nicht unglaublich ineffizient?

Ja.

Was wäre effizienter?

if (sequence.Any())

Warum ist die effiziente?

Weil es versucht, über eins Element zu iterieren. Wenn es gelingt, dann ist Any wahr; Wenn es fehlschlägt, ist Any falsch. Sie müssen nicht die Anzahl der Jelly Beans im Glas zählen, um zu wissen, ob es mehr als Null gibt. Sie müssen nur nachsehen, ob es mindestens eine gibt.

Zusätzlich zu wesentlich effizienterem Code liest sich der Code nun wie die beabsichtigte Bedeutung des Codes. Wenn Sie fragen möchten: "Gibt es Gegenstände in der Liste?" dann frage "Gibt es irgendwelche Gegenstände in der Liste?" und nicht "ist die Anzahl der Elemente in der Liste größer als Null?"

Was ist mit der Capacity Eigenschaft einer Liste?

Das sagt Ihnen, wie viel Speicherplatz in den internen Datenstrukturen der Liste vorab reserviert wurde. Dies ist die Anzahl der Elemente, die die Liste speichern kann, bevor sie mehr Speicher zuweisen muss.

+0

"Wir fragen die Sequenz zur Laufzeit ab, um zu sehen, ob es eine Liste mit einer Count-Eigenschaft gibt, die effizient berechnet werden kann." Was meinst du damit? Suchen Sie nach einer Eigenschaft namens "Count" oder überprüfen Sie, ob ICollection implementiert ist? Der zweite hat lustige Sonderfälle, wenn Sie die Kovarianz 'IEnumerable 'verwenden. – CodesInChaos

+0

@CodeInChaos: Wenn man über Reflection nach einer Eigenschaft namens Count sucht, wäre das sowohl langsam als auch unzuverlässig. Wir suchen nach einer Implementierung der Schnittstelle. Und ja, Sie können als Ergebnis von Kovarianzproblemen falsche Negative erhalten. Wenn es schmerzt, wenn du das tust, dann tu das nicht. –

+2

@CodeInChaos Wenn die Überprüfung für 'ICollection ' fehlschlägt, sucht der Code nach nicht generischer 'ICollection'. Daher sind die meisten Framework-Sammlungen vor dem Kovarianzproblem geschützt. – phoog

2

Verwenden Sie stattdessen diesen Code: list.Any(). Es kann langsamer sein als List<>.Count, aber funktioniert für jeden IEnumerable <> auf effizienteste Weise.

Capacity kann größer als Count sein. Es wird verwendet, wenn Sie später viele Elemente hinzufügen möchten.

Imlementation von List.Count ist die folgende (es ist wirklich O (1)):

public int Count 
{ 
    get 
    { 
    return this._size; // this is a field 
    } 
} 
+2

Während '.Any()' gegenüber '.Count()> 0' vorzuziehen ist, ist es etwas weniger effizient, da es einen Enumerator für die Auflistung erstellt. – Gabe

+0

fot Liste oder irgendeine Sammlung, die c speichert –

2

Count ist O(1) Operation auf Liste.

Es ist der schnellste Weg möglich.

Anzahl: Dies ist eine Anzahl von Elementen in der Liste tatsächlich vorhanden.

Capcity: Erläutert bessere Dokumentation:

Ruft die Gesamtanzahl der Elemente der interne Datenstruktur ohne Ändern der Größe aufnehmen kann.

1

Die Kapazität sagt Ihnen nicht, wie viele Objekte in Ihrer Liste sind - wie viel die Liste bereit ist.

Von MSDN:

Capacity is the number of elements that the List<T> can store before resizing is required, while Count is the number of elements that are actually in the List<T>. 

List.Count ist super schnell und ist eine Eigenschaft zugegriffen, während List.Count() ist von IEnumerable und ich glaube, eine vollständige Aufzählung durch die Liste zu tun hat.

6

Die Count Eigenschaft in List<T> - und alle anderen ICollection<T> Implementierungen im BCL - ist ein O (1) Betrieb, das bedeutet, es ist schnell und unabhängig von der Anzahl der Anzahl der Elemente in der Liste.

Es gibt auch eine Erweiterungsmethode Count(), die auf jedem IEnumerable<T> aufgerufen werden kann. Diese Methode ist O (n), was bedeutet, dass ihre Laufzeit von der Anzahl der Elemente in der Aufzählung abhängt. Es gibt jedoch eine Ausnahme: Wenn das Enumerable wirklich eine Implementierung von oder ICollection ist, verwendet es die Count-Eigenschaft, die es erneut zu einer O (1) -Operation macht.


Die Capacity Eigenschaft ist in der Regel nichts, was man sich Sorgen machen müssen.

+1

Nun, wenn man bedenkt, dass Op über 986.000 Elemente in der Liste spricht, kann eine geschickte Verwaltung der Kapazität am richtigen Ort * erhebliche Vorteile bringen. – Tigran

+0

Die Kapazität wird jedes Mal verdoppelt, wenn sie getroffen wird. Die Verwaltung der Kapazität bringt nur dann einen echten Vorteil, wenn Sie viele Listen füllen. –

+0

Das, was ich meine: es * kann * Vorteile bringen in einigen Situationen (Beispiel CAD-Programme) – Tigran