ProgrammierungiOS Entwickler

Was sind Lazy Collections in Swift und wann ist ihre Verwendung gerechtfertigt?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Lazy Collections (faule Sammlungen) sind ein spezieller Mechanismus, der in Swift 2 eingeführt wurde und es ermöglicht, Berechnungen über Sammlungen bis zum Zeitpunkt des tatsächlichen Zugriffs auf das Ergebnis zu verzögern. Ursprünglich gaben die Standardmethoden von Sammlungen (z. B. map, filter) das vollständig berechnete Ergebnis einer neuen Sammlung zurück, was manchmal zu unnötigem Speicher- und Zeitaufwand führte, insbesondere bei großen Arrays oder langen Transformationsketten.

Das Problem besteht in der überflüssigen Erstellung von Zwischenkollektionen. Jeder Aufruf von map oder filter erstellt eine neue Kopie der Daten, was bei mehrfachem Transformieren die Leistung des Programms spürbar beeinträchtigt.

Die Lösung besteht darin, faule Sammlungen mit dem Attribut .lazy zu verwenden. Swift fasst alle Operationen in einer Kette zusammen und berechnet nur die Elemente, auf die tatsächlich zugegriffen wird.

Beispielcode:

let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // Nur die ersten 5 Werte werden berechnet

Hauptmerkmale:

  • Berechnungen werden nur bei Zugriff auf das Element (on-demand) durchgeführt.
  • Es werden keine Zwischenarrays bei map/filter-Ketten erstellt.
  • Ermöglicht eine Einsparung von Speicher und Zeit bei großen Datenmengen.

Tricks mit Fragen.

Frage 1: Gibt let b = a.lazy.map { ... } sofort das berechnete Ergebnis zurück?

Nein, bei der Verwendung von .lazy und den Methoden map/filter wird das Berechnungsergebnis nur bei direktem Zugriff auf die Daten zurückgegeben (z. B. über for-in, first, reduce).

Beispielcode:

let array = [1, 2, 3] let mapped = array.lazy.map { x in print("processing\(x)") return x * 2 } // An diesem Punkt wird nichts ausgegeben let first = mapped.first // Hier beginnen die Berechnungen und es erscheint eine Ausgabe

Frage 2: Kann man nach .lazy ein neues Element zur ursprünglichen Sammlung hinzufügen und wird es auch verarbeitet, wenn später auf das Ergebnis zugegriffen wird?

Nein, die Lazy Collection spiegelt den Zustand der Sammlung zum Zeitpunkt der Erstellung der faulen Darstellung wider. Später hinzugefügte Elemente werden nicht berücksichtigt.

Frage 3: Ist die Verwendung von .lazy für kleine Sammlungen (<100 Elemente) effizient?

Nein, der Gewinn von faulen Berechnungen ist bei kleinen Sammlungen praktisch nicht spürbar, und manchmal hat der zusätzliche Overhead negative Auswirkungen auf die Leistung.

Häufige Fehler und Anti-Patterns

  • Manchmal wird vergessen, auf das Ergebnis der faulen Kette zuzugreifen und es wird angenommen, dass die Daten bereits berechnet sind.
  • .lazy wird auf kleinen Arrays verwendet, wodurch der Code komplizierter wird, ohne Leistungsgewinne zu erzielen.
  • Die ursprüngliche Sammlung wird nach der Erstellung der faulen Darstellung geändert, und es wird erwartet, dass die Änderungen übernommen werden.

Beispiele aus dem Leben

Negativer Fall

Im Projekt wurde gedankenlos .lazy für alle map/filter, sogar auf kleinen Sammlungen, verwendet.

Vorteile:

  • Vereinheitlichung des Code-Stils.

Nachteile:

  • Die Leistung wurde aufgrund der ständigen Erstellung fauler Hüllen verringert.
  • Es traten Bugs auf: Berechnungen fanden nicht statt und die Daten wurden nicht rechtzeitig verarbeitet.

Positiver Fall

Wir haben Berichte über eine große Transaktionsdatenbank mit .lazy nur für Funktionen refaktoriert, bei denen tatsächlich lange Transformationsketten vorlagen.

Vorteile:

  • Die Ausführungszeit wurde spürbar verkürzt.
  • Es wurde weniger Speicher benötigt, insbesondere wenn nur die ersten paar Elemente des Ergebnisses abgerufen wurden.

Nachteile:

  • Es war zusätzliche Dokumentation für solche Codeabschnitte erforderlich.