Lazy Collections (ленивые коллекции) — это особый механизм, появившийся в Swift 2, который позволяет откладывать вычисления над коллекциями до момента непосредственного обращения к результату. Изначально стандартные методы коллекций (например, map, filter) возвращали полностью вычисленный результат новой коллекции, что иногда вело к ненужным затратам памяти и времени, особенно при работе с большими массивами или цепочками преобразований.
Проблема заключается в избыточном создании промежуточных коллекций. Каждый вызов map или filter создает новую копию данных, что при множественных преобразованиях заметно снижает производительность программы.
Решение — использовать ленивые коллекции с помощью свойства .lazy. Swift объединяет все операции в одну цепочку и вычисляет только те элементы, к которым реально обращаются.
Пример кода:
let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // Только 5 первых значений будут посчитаны
Ключевые особенности:
Вопрос 1: Возвращает ли let b = a.lazy.map { ... } сразу результат вычисления?
Нет, при использовании .lazy и методов map/filter результат вычисления возвращается только при непосредственном обращении к данным (например, через for-in, first, reduce).
Пример кода:
let array = [1, 2, 3] let mapped = array.lazy.map { x in print("processing\(x)") return x * 2 } // На этом этапе ничего не выведется let first = mapped.first // Вот тут начнут выполняться вычисления и появится вывод
Вопрос 2: Можно ли после .lazy добавить новый элемент в исходную коллекцию и он тоже будет обработан, если обратиться к результату позднее?
Нет, Lazy Collection отражает состояние коллекции на момент создания ленивого представления. Позже добавленные элементы не будут учитываться.
Вопрос 3: Является ли использование .lazy эффективным для маленьких коллекций (<100 элементов)?
Нет, для маленьких коллекций выигрыш от ленивых вычислений практически незаметен, а иногда лишний оверхед отрицательно влияет на производительность.
В проекте бездумно использовали .lazy для всех map/filter даже на маленьких коллекциях.
Плюсы:
Минусы:
Рефакторили отчеты по большой базе транзакций с применением .lazy только для функций, где реально были длинные цепочки преобразований.
Плюсы:
Минусы: