【发布时间】:2020-01-05 22:03:48
【问题描述】:
进行惰性转换的最佳方法是什么(不创建中间集合) 当
在平面图之前和之后进行过滤 平面地图
连接集合
通常我使用 withFilter 进行这种惰性过滤,但在更复杂的用例中它并不完全有效
过滤器 + flatMap
1) 幼稚的方法
case class Item(size: Int, color: String)
// Assume an order can have a lot of items
case class Orders(price:Int, country: String, items: Seq[C])
val orders: Seq[Orders]
val ca = orders.filter(_.country = "CA").flatMap(_.items).filter(_.size > 4)
val rest = orders.filter(_.country != "CA").flatMap(_.items).filter(_.size > 6)
val res = (ca ++ rest).filter(_.color == "red").take(100)
2) 单一路径,但为每个订单创建中间项目集合。而且我认为 flatMap 也会产生一个集合
orders.flatMap {
case order if order.country = "CA") => order.items.filter(_.size > 4)
case order => order.items
}.withFilter(_.color == "red").take(100)
3) 迭代器。但我不能 100% 确定它会如何执行
orders.iterator.flatMap {
case order if order.country = "CA") => order.items.iterator.filter(_.size > 4)
case order => order.items.iterator
}.filter(_.color == "red").take(100)
4) 流。
orders.toStream.flatMap {
case order if order.country = "CA") => order.items.toStream.filter(_.size > 4)
case order => order.items.toStream
}.filter(_.color == "red").take(100)
5)视图:不确定是否会为每个订单中的项目创建中间集合(我认为会),而且总的来说我不喜欢视图(忘记“强制”会导致错误)
orders.view.flatMap {
case order if order.country = "CA") => order.items.filter(_.size > 4)
case order => order.items
}.filter(_.color == "red").take(100)
连接
类似的选项,但用于
val items1 = items.filter(filter1)
val items2 = items.filter(filter2)
val items3 = items.filter(filter3)
val res = (items1 ++ items2 ++ items3).filter(_.color == "Red").take(100)
【问题讨论】:
-
可能 Stream 将是最节省内存的。但赌注是进行基准测试,特别是如果这对您非常重要。另外,您可能想给fs2 看看。
-
查看是您的最佳选择。视图不会创建新集合。您可以从这里的源代码中看到github.com/scala/scala/blob/v2.13.0/src/library/scala/… 对视图的每个操作都会创建一个包含函数或其他必要信息的新普通对象,但不会创建集合。