惰性获取与过滤
对无限流进行切片。
惰性获取与过滤 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
惰性消费
只有在消费 LazyList 时,它的真正价值才会显现。take、filter 和 map 等操作会保持惰性,只计算您最终强制求值的单元。
本课将介绍关键的转换器,以及如何在合适的时机结束惰性求值。
take(n)
take(n) 返回一个至多包含前 n 个元素的 LazyList,并且它本身仍是惰性的。在您强制求值结果之前,不会计算任何内容。
这是限制无限流范围的安全方式。
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)
}惰性筛选
LazyList 上的 filter 是惰性的:只有下游消费者拉取元素时,它才会测试相应元素。
将它与 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 等终结操作会强制获取结果。
请防范无限流上无法满足条件的筛选。现在,您已经可以放心地生成和消费惰性序列了。
常见问题解答
「惰性获取与过滤」课时是免费的吗?
是的 — 「惰性获取与过滤」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
「惰性获取与过滤」这节课中我会学到什么?
对无限流进行切片。 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「惰性获取与过滤」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?
能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 理解惰性求值
- 构建 LazyList
- 无限流
- 惰性获取与过滤