用filter代替filter
在使用filter,flatmap等函数的时候,使用Filter来代替filter,总是更高效的吗?
为什么只支持map,flatmap和foreach? (像forall /期望的function也存在)
从scala文档:
Note: the difference between c filter p and c withFilter p is that the former creates a new collection, whereas the latter only restricts the domain of subsequent map, flatMap, foreach, and withFilter operations.
因此, filter
将采集原始集合并生成一个新的集合,但是withFilter
将非严格地(即,懒惰地)将未过滤的值传递给后来的map / flatMap / withFilter调用,并通过(过滤的)集合保存第二遍。 因此,通过这些后续的方法调用将会更高效。
实际上, withFilter
是专门为这些方法的链条而devise的,这是一种理解去除的方法。 没有其他的方法(如forall
/ exists
)需要这个,所以它们还没有被添加到FilterMonadic
的withFilter
返回types中。
除了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
的事实对filter没有影响,因为filter已经完成。 再一次,在Scala 2.8中,使用withFilter
解决了这个问题。 当使用withFilter
器时,每次在map
方法中访问元素时都会评估条件。
参考 : – 第120页,斯卡拉在行动(涵盖斯卡拉2.10),曼宁出版社,Milanjan Raychaudhuri – Odersky关于理解翻译的想法
用于产量可以是一个工作,例如:
for { e <- col; if e isNotEmpty } yield e.get(0)
作为一种解决方法,您可以仅使用map
和flatMap
来实现其他函数。
而且,这个优化在小集合上是无用的…