什么是集合的视图以及您何时想要使用它们?

问题描述 投票:51回答:4

在Scala中,对于许多(所有?)类型的集合,您可以创建视图。

究竟是什么视图以及视图有用的目的是什么?

scala views scala-collections
4个回答
47
投票

视图是集合的非严格版本。这意味着元素是在访问时计算的,而不是像普通集合中那样急切地计算。

作为示例,请使用以下代码:

val xs = List.tabulate(5)(_ + 1)
val ys = xs.view map { x => println(x); x * x }

只是这不会打印任何东西,但每次访问列表将执行计算并打印值,即每次调用ys.head将导致打印1。如果你想再次获得该系列的严格版本,可以在上面调用force。在这种情况下,您将看到打印出的所有数字。

视图的一个用途是当您需要遍历计算成本高昂的值集合时,您一次只需要一个值。此外,您还可以通过调用toStream来构建延迟序列,这些序列也会缓存已评估的元素。


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

而:

    list.map(v => Transform(v)).collectFirst{case Transform(3) => println("found")}

打印:

Transform 1
Transform 2
Transform 3
Transform 4
Transform 5
found

8
投票

参见ViewsScala 2.8 Collections API

除了Stream之外,Scala集合默认在所有变换器中都是严格的,val view = Range(1,9).view.懒洋洋地实现了所有变换器方法。但是,有一种系统的方法可以将每个集合转换为惰性集合,反之亦然,这是基于集合视图。视图是一种特殊的集合,代表一些基本集合,但是懒惰地实现所有变换器。

...

您可能想要考虑使用视图有两个原因。首先是表现。您已经看到,通过将集合切换到视图,可以避免构建中间结果。这些节省非常重要。

...

第二个用例适用于可变序列的视图。这些视图上的许多变换器函数提供了进入原始序列的窗口,然后可以使用该窗口选择性地更新该序列的一些元素。


0
投票

view用于延迟计算,但不用于保存内存。

当您针对集合创建视图时,已经为集合分配了内存。

当用Range(1,1000000000)创建视图时,集合已经被分配了内存,如果它太大了,比方说,qazxswpoi,OOM无法避免

© www.soinside.com 2019 - 2024. All rights reserved.