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:
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.
Im Projekt wurde gedankenlos .lazy für alle map/filter, sogar auf kleinen Sammlungen, verwendet.
Vorteile:
Nachteile:
Wir haben Berichte über eine große Transaktionsdatenbank mit .lazy nur für Funktionen refaktoriert, bei denen tatsächlich lange Transformationsketten vorlagen.
Vorteile:
Nachteile: