在随后应用诸如map,flatmap等功能时,使用withFilter而不是filter总是表现更好吗?
为什么只支持map,flatmap和foreach?(预期功能如forall / exists)
Answers:
从Scala文档:
注:之间的区别
c filter p,并c withFilter p为前者创造一个新的集合,而后者只限制后续的域map,flatMap,foreach,和withFilter操作。
因此,filter将采取原始集合和产生一个新的集合,但withFilter将非严格(即懒洋洋地)到后来通过未过滤的值map/ flatMap/withFilter调用,节省通过(过滤)收集第二遍。因此,当传递到这些后续方法调用时,它将更加高效。
实际上,withFilter是专门为与这些方法的链一起使用而设计的,这对于理解方法是毫无用处的。不需要其他方法(例如forall/ exists),因此尚未将它们添加到的FilterMonadic返回类型中withFilter。
view,如果你想映射/过滤器偷懒。
view和之间的确切区别是withFilter什么?为什么视图不用于for-loops?
Don’t create temporary collections在链接的部分中进行搜索。
withFilter,Martin Odersky自己在Coursera的Scala课程中显式使用了它,我强烈建议这样做。考虑到他这样做,尽管差异通常只有1个字符,但这样做也可能给其他人带来安慰。例如seq.view filter p对seq withFilter p。
除了Shadowlands的出色答案外,我想举一个直观的示例,说明filter和之间的区别withFilter。
让我们考虑以下代码
val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
go = false
i
}
大多数人期望result等于List(1)。自Scala 2.8起就是这种情况,因为理解力被翻译成
val result = list withFilter {
case i => go
} map {
case i => {
go = false
i
}
}
如您所见,翻译将条件转换为withFilter。在Scala 2.8之前的版本中,对理解的理解如下:
val r2 = list filter {
case i => go
} map {
case i => {
go = false
i
}
}
使用filter,其值result将大不相同:List(1, 2, 3)。我们正在制作go标志的事实false对过滤器没有影响,因为过滤器已经完成。同样,在Scala 2.8中,使用可以解决此问题withFilter。当withFilter被使用时,条件被评估每一个元件被一个内部访问的时间map的方法。
参考:-第120页,Scala的运用(涵盖Scala 2.10),Manning出版物,Milanjan Raychaudhuri- Odersky的理解翻译思想
未实现forall / exists的主要原因是该用例是:
要实现永久/存在,我们需要获得所有要素,从而消除惰性。
因此,例如:
import scala.collection.AbstractIterator
class RandomIntIterator extends AbstractIterator[Int] {
val rand = new java.util.Random
def next: Int = rand.nextInt()
def hasNext: Boolean = true
}
//rand_integers is an infinite random integers iterator
val rand_integers = new RandomIntIterator
val rand_naturals =
rand_integers.withFilter(_ > 0)
val rand_even_naturals =
rand_naturals.withFilter(_ % 2 == 0)
println(rand_even_naturals.map(identity).take(10).toList)
//calling a second time we get
//another ten-tuple of random even naturals
println(rand_even_naturals.map(identity).take(10).toList)
请注意,ten_rand_even_naturals仍然是迭代器。只有当我们调用toList时,随机数才会生成并在链中进行过滤
请注意,map(identity)等同于map(i => i),在这里使用它是为了将withFilter对象转换回原始类型(例如,集合,流,迭代器)
使用yield可以解决,例如:
for {
e <- col;
if e isNotEmpty
} yield e.get(0)
解决方法是,可以仅使用map和实现其他功能flatMap。
而且,这种优化对小型馆藏毫无用处……