繁体   English   中英

在 Scala 中,“视图”是做什么的?

[英]In Scala, what does "view" do?

具体来说,我在这里查看问题 1

http://pavelfatin.com/scala-for-project-euler/

列出的代码如下

val r = (1 until 1000).view.filter(n => n % 3 == 0 || n % 5 == 0).sum

我可以关注除“视图”之外的所有内容。 事实上,如果我取出视图,代码仍然可以编译并产生完全相同的答案。

View 生成一个惰性集合,因此对例如filter的调用不会评估集合的每个元素。 元素只有在被显式访问后才会被评估。 现在sum确实可以访问所有元素,但是通过view调用filter不会创建完整的 Vector。 (见史蒂夫的评论)

使用视图的一个很好的例子是:

scala> (1 to 1000000000).filter(_ % 2 == 0).take(10).toList
java.lang.OutOfMemoryError: GC overhead limit exceeded

在这里 Scala 尝试创建一个包含1000000000个元素的集合,然后访问前 10 个元素。但是查看:

scala> (1 to 1000000000).view.filter(_ % 2 == 0).take(10).toList
res2: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

我对 Scala 不太了解,但也许这个页面可能会有所帮助......

有两种主要的方法来实现转换器。 一个是严格的,即所有元素的新集合都是由转换器构造的。 另一种是非严格或惰性的,即只为结果集合构造一个代理,并且它的元素仅在需要时才被构造。

视图是一种特殊的集合,代表一些基本集合,但会延迟实现所有转换器。

所以听起来好像代码在没有view的情况下仍然可以工作,但理论上可能会做一些额外的工作,以严格而不是懒惰的方式构建集合的所有元素。

当您在一个集合上链接多个转换时,我们会创建许多中间 collections 立即丢弃。 例如,在以下代码中:

@ val myArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
@ val myNewArray = myArray.map(x => x + 1).filter(x => x % 2 == 0).slice(1, 3)

myNewArray: Array[Int] = Array(4, 6)

.map .filter .slice操作链最终遍历集合 3 次,创建了三个新的 collections,但只有最后一个集合最终存储在myNewArray中,其他集合被丢弃。

myArray
1,2,3,4,5,6,7,8,9

map(x => x + 1)
2,3,4,5,6,7,8,9,10

filter(x => x % 2 == 0)
2,4,6,8,10

slice(1, 3)
myNewArray
4,6

这种中间 collections 的创建和遍历是浪费的。 如果您有很长的集合转换链成为性能瓶颈,您可以使用.view方法和.to将操作融合在一起:

@ val myNewArray = myArray.view.map(_ + 1).filter(_ % 2 == 0).slice(1, 3).to(Array)
myNewArray: Array[Int] = Array(4, 6)

map/filter/slice转换操作之前使用.view会将新集合的实际遍历和创建推迟到稍后,当我们调用.to将其转换回具体的集合类型时:

myArray
1,2,3,4,5,6,7,8,9

view map filter slice to

myNewArray
4,6

这允许我们只用一次遍历来执行这个map/filter/slice转换链,并且只创建一个 output 集合。 这减少了不必要的处理量和 memory 分配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM