Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Lazy Collection?
Lazy Collection — это механизм в Swift для отложенного (ленивого) вычисления элементов коллекции. Вместо того, чтобы сразу вычислить все результаты, операции выполняются только когда они действительно нужны.
Основной концепт
Обычная коллекция выполняет операции немедленно:
let numbers = [1, 2, 3, 4, 5]
// Эта операция создаёт НОВЫЙ массив с результатами
let squared = numbers.map { $0 * $0 }
// Результат: [1, 4, 9, 16, 25]
// Все элементы вычислены, память выделена
LazySequence откладывает вычисления:
let numbers = [1, 2, 3, 4, 5]
// Это НЕ создаёт новый массив!
let lazySquared = numbers.lazy.map { $0 * $0 }
// Вычисления отложены, память не выделена
// Вычисления происходят ТОЛЬКО здесь при итерации
for squared in lazySquared {
print(squared) // 1, 4, 9, 16, 25
}
Практический пример
let largeArray = Array(1...1_000_000)
// ❌ Неэффективно: создаёт промежуточные массивы
let eager = largeArray
.map { $0 * 2 } // создаёт массив из 1М элементов
.filter { $0 > 1000 } // создаёт ещё один массив
.prefix(10) // берёт только первые 10!
// Невыгодно: 2 миллиона элементов обработано, но нужно 10
// ✅ Эффективно: ленивые вычисления
let lazy = largeArray
.lazy
.map { $0 * 2 } // ещё НЕ вычислено
.filter { $0 > 1000 } // ещё НЕ вычислено
.prefix(10) // ТОЛЬКО здесь вычисляются нужные элементы
for value in lazy {
print(value) // обработано только нужное количество элементов
}
Методы, работающие с Lazy
Методы, которые работают с lazy (и остаются lazy)
let numbers = [1, 2, 3, 4, 5].lazy
// Остаются ленивыми (не вычисляют сразу):
let mapped = numbers.map { $0 * 2 } // LazyMapSequence
let filtered = numbers.filter { $0 > 2 } // LazyFilterSequence
let flattened = numbers.flatMap { 1...$0 } // LazyFlatMapSequence
let zipped = numbers.zip(numbers) // LazyZipSequence
Методы, которые "прерывают" lazy
let numbers = [1, 2, 3, 4, 5].lazy
// Эти операции ВЫЧИСЛЯЮТ все значения сразу:
let array = Array(numbers) // Создаёт массив
let count = numbers.count // Подсчитывает всё
let first = numbers.first // Нужно проверить всё
let contains = numbers.contains(3) // Может нужно всё
Таблица: Eager vs Lazy
| Операция | Eager | Lazy |
|---|---|---|
| Когда выполняется | Сразу | При итерации |
| Память | Создаёт промежуточные массивы | Минимальная |
| Скорость | Медленнее для больших данных | Быстрее для коротких результатов |
| Тип | Array | LazySequence |
| Пример | array.map { } | array.lazy.map { } |
Реальные примеры использования
1. Большие файлы
// Обработка большого файла строка за строкой
func processLargeFile(_ path: String) {
let lines = readLines(path) // читает весь файл
lines
.lazy
.map { $0.trimmingCharacters(in: .whitespaces) } // ленивое трим
.filter { !$0.isEmpty } // ленивый фильтр
.forEach { processLine($0) } // обрабатывает по одной
}
2. Бесконечные последовательности
func fibonacci() -> LazySequence<UnfoldSequence<Int, (Int, Int)>> {
return sequence(state: (0, 1)) { state in
let next = state.0 + state.1
state = (state.1, next)
return next
}.lazy
}
// Берём первые 10 чисел Фибоначчи
let first10 = fibonacci().prefix(10)
for num in first10 {
print(num) // вычисляются только нужные
}
3. API запросы
func fetchUsersPaginated(pageSize: Int) -> LazySequence<LazyMapSequence<[Int], User>> {
return (1...).lazy.map { page in
// Каждый page загружается ТОЛЬКО когда на него обращаются
fetchPage(page: page, size: pageSize)
}.flatMap { $0 }
}
// Используем
for user in fetchUsersPaginated(pageSize: 20).prefix(100) {
print(user) // загружаются только нужные страницы
}
Производительность
Тест на производительность
import Foundation
let numbers = Array(1...10_000)
// Eager
let startEager = Date()
let eagerResult = numbers
.map { $0 * 2 }
.filter { $0 > 5000 }
.prefix(5)
let timeEager = Date().timeIntervalSince(startEager)
// Lazy
let startLazy = Date()
let lazyResult = numbers
.lazy
.map { $0 * 2 }
.filter { $0 > 5000 }
.prefix(5)
.forEach { _ in } // материализуем
let timeLazy = Date().timeIntervalSince(startLazy)
print("Eager: \(timeEager)s") // медленнее
print("Lazy: \(timeLazy)s") // быстрее
Когда использовать Lazy
✅ Используй Lazy когда:
- Работаешь с большими коллекциями
- Нужны первые N элементов, а не все
- Данные дорого вычислять (API запросы, файлы)
- Хочешь цепочку трансформаций без промежуточных массивов
- Имеешь бесконечные последовательности
❌ Не используй Lazy когда:
- Коллекция маленькая (< 100 элементов)
- Нужны все элементы (всё равно будут вычислены)
- Нужна случайный доступ по индексу
- Нужна производительность для одноразовой итерации
Вывод
Lazy Collection — это мощная оптимизация для работы с большими данными и сложными трансформациями. Она откладывает вычисления до момента, когда они действительно нужны, экономя память и время обработки. Это особенно полезно при работе с файлами, API запросами и бесконечными последовательностями.