在Scala中,对于许多(所有?)类型的集合,您可以创建视图。
视图究竟是什么,视图有哪些用途?
答案 0 :(得分:47)
视图是集合的非严格版本。这意味着元素是在访问时计算的,而不是像普通集合中那样急切。
作为示例,请使用以下代码:
val xs = List.tabulate(5)(_ + 1)
val ys = xs.view map { x => println(x); x * x }
这不会打印任何内容,但每次访问列表都会执行计算并打印值,即每次调用ys.head
都会导致打印1
。如果您想再次获得该集合的严格版本,可以在其上调用force
。在这种情况下,您将看到打印出的所有数字。
视图的一个用途是当您需要遍历计算成本高昂的值集合时,您一次只需要一个值。此外,您还可以通过调用toStream
来构建延迟序列,这些序列也会缓存已评估的元素。
答案 1 :(得分:12)
一个用例是当你需要收集元素转换的第一个结果时:
case class Transform(n: Int) { println("Transform "+n)}
val list = List(1,2,3,4,5)
list.view.map(v => Transform(v)).collectFirst{case Transform(3) => println("found")}
打印:
Transform 1
Transform 2
Transform 3
found
while:
list.map(v => Transform(v)).collectFirst{case Transform(3) => println("found")}
打印:
Transform 1
Transform 2
Transform 3
Transform 4
Transform 5
found
答案 2 :(得分:8)
请参阅Views中的Scala 2.8 Collections API。
除了
Stream
之外,Scala集合默认在所有变换器中都是严格的,它们懒洋洋地实现了所有变换器方法。但是,有一种系统的方法可以将每个集合转换为惰性集合,而反之亦然,它基于集合视图。 视图是一种特殊的集合,代表一些基本集合,但是懒惰地实现所有变换器。...
您可能想要考虑使用视图有两个原因。首先是表现。您已经看到,通过将集合切换到视图,可以避免构建中间结果。这些节省非常重要。
...
第二个用例适用于可变序列的视图。这些视图上的许多变换器函数提供了一个进入原始序列的窗口,然后可以用它来选择性地更新该序列的某些元素。
答案 3 :(得分:0)
视图用于延迟计算,但不用于保存内存。
当您针对集合创建视图时,已经为集合分配了内存。
使用val view = Range(1,9).view.
创建视图时,已经为该集合分配了内存,如果它太大,例如Range(1,1000000000)
,则OOM无法避免