Ленивое извлечение и фильтрация
Выделяйте части бесконечных потоков.
«Ленивое извлечение и фильтрация» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Ленивое потребление
Настоящая ценность LazyList проявляется при его потреблении. Такие операции, как take, filter и map, сохраняют ленивость и вычисляют только те ячейки, которые Вы в итоге принудительно запрашиваете.
В этом уроке рассматриваются основные преобразования и способы вовремя завершить ленивые вычисления.
take(n)
take(n) возвращает LazyList, содержащий не более первых n элементов, и сам остаётся ленивым. Ничего не вычисляется, пока Вы не запросите результат принудительно.
Это безопасный способ ограничить бесконечный поток.
object Demo extends App {
val first5 = LazyList.from(1).take(5)
println(first5.toList)
}takeWhile
takeWhile(p) выдаёт элементы, пока выполняется предикат, а затем останавливается при первой неудаче.
Для бесконечного потока это удобное условие остановки, не требующее заранее знать количество элементов.
object Demo extends App {
val small = LazyList.from(1).takeWhile(_ < 6)
println(small.toList)
}drop и dropWhile
drop(n) пропускает первые n элементов; dropWhile(p) пропускает элементы, пока выполняется предикат. Оба метода возвращают ленившийся остаток.
Используйте их, чтобы перейти к нужному месту потока перед извлечением фрагмента.
object Demo extends App {
val rest = LazyList.from(1).drop(3).take(3)
println(rest.toList)
}Ленивый фильтр
filter для LazyList является ленивым: он проверяет элементы только по мере того, как следующий потребитель их запрашивает.
В сочетании с take Вы обработаете ровно столько исходных элементов, сколько необходимо, и ни одного лишнего.
object Demo extends App {
val evens = LazyList.from(1).filter(_ % 2 == 0)
println(evens.take(4).toList)
}Наблюдаем потребление
Добавьте печать внутри предиката, чтобы увидеть, как мало элементов проверяется. Фильтр выполняется только до тех пор, пока take не получит нужное количество элементов.
Запустите этот код: количество строк «check» показывает вычисление по требованию, а не обработку всего потока.
object Demo extends App {
val r = LazyList.from(1).filter { n =>
println("check " + n); n % 3 == 0
}
println(r.take(2).toList)
}Цепочка map и filter
Вы можете объединять преобразования в цепочку: весь конвейер сохраняет ленивость и объединяется для каждого элемента. Каждый исходный элемент проходит через map, затем через filter только в момент запроса.
Промежуточные полные коллекции не создаются.
object Demo extends App {
val r = LazyList.from(1).map(_ * _).filter(_ > 10).take(3)
println(r.toList)
}find: ранняя остановка
find(p) возвращает первый подходящий элемент как Option, принудительно вычисляя элементы только до него. Это идеально подходит для поиска в бесконечном потоке.
Как только совпадение найдено, вычисление немедленно останавливается.
object Demo extends App {
val firstBig = LazyList.from(1).find(_ * _ > 50)
println(firstBig)
}headOption и exists
headOption безопасно заглядывает в первый элемент; exists(p) вычисляет элементы только до нахождения совпадения (или бесконечно, если его нет). Используйте exists для бесконечных потоков только при гарантии, что совпадение будет найдено.
Оба метода останавливаются как можно раньше.
object Demo extends App {
val has = LazyList.from(1).exists(_ == 7)
println(has)
}Принудительное вычисление результата
Ленивые преобразования описывают работу, а конечная операция принудительно запускает её. toList, foreach, sum и foldLeft потребляют ограниченный поток и создают конкретное значение.
Всегда ограничивайте бесконечный поток перед конечной операцией, которой требуется обработать его целиком.
object Demo extends App {
val total = LazyList.from(1).take(100).sum
println(total)
}Проблемы при фильтрации
filter, которому ничего не подходит, превращает ограниченный take в бесконечный поиск. LazyList.from(1).filter(_ < 0).take(1) зависает навсегда.
Убедитесь, что предикаты могут выполниться, или объединяйте фильтрацию с takeWhile, чтобы гарантировать завершение.
Быстрая проверка
Проверьте, насколько хорошо Вы поняли ленивое потребление.
Итоги
take, takeWhile, drop, filter и map сохраняют ленивость и объединяются для каждого элемента; find, exists и headOption останавливаются рано; конечные операции, такие как toList и sum, принудительно вычисляют результат.
Остерегайтесь невыполнимых фильтров в бесконечных потоках. Теперь Вы умеете уверенно создавать и потреблять ленивые последовательности.
Изучай Scala с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 39
- Уроки
- 143
Часто задаваемые вопросы
Урок «Ленивое извлечение и фильтрация» бесплатный?
Да — полный текст урока «Ленивое извлечение и фильтрация» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Чему я научусь в уроке «Ленивое извлечение и фильтрация»?
Выделяйте части бесконечных потоков. Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?
Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Ленивое извлечение и фильтрация»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?
Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Объяснение ленивых вычислений
- Создание LazyList
- Бесконечные потоки
- Ленивое извлечение и фильтрация