09-scala的yield、lazy和集合的view

197 阅读1分钟

yield

yield一般和for循环配合使用,yield每次会把for迭代的数据放到Vector中,然后在for循环结束后返回集合。直接给出代码实例:

package example

object MyExample {

  def main(args: Array[String]): Unit = {
    val res = for (i <- 1 to 10) yield i
    println(res.toString)
  }
}

代码输出:

Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

lazy

延迟计算用的,变量声明的时候不会立刻执行计算,而是在第一次用到的时候计算。给出代码实例:

package example

object MyExample {

  def generateName(): String = {
    println("In generateName")
    "Foo"
  }

  def main(args: Array[String]): Unit = {
    lazy val name = generateName()  // 这里不会立刻执行
    println("before print name")
    println(name)
  }
}

代码输出:

before print name
In generateName
Foo

我们发现name赋值的时候没有立刻执行,而是第一次获取该变量的时候才执行的。

view

一般用于集合。集合的视图用于延迟计算,我们在写视图的时候,集合的转换等不会立刻执行计算,而是等到需要的时候才会计算,视图只是表述了一个计算步骤。view的时空复杂度都是O(N)O(N)。如果想要把视图转换成集合,需要调用to关键字。

给出一个代码实例:

package example

object MyExample {

  def main(args: Array[String]): Unit = {
    val nums = Array(1, 2, 3, 4, 5)
    val v = nums.view
      .map(_ * 2)
      .map(i => {
        println(s"convert $i")
        i + 2
      })
      .slice(1, 3)
    println(s"after contruct view, v type: ${v.getClass}")
    val vv = v.to(Vector)
    println(vv.toString)
  }
}

代码输出:

after contruct view, v type: class scala.collection.IndexedSeqView$Slice
convert 4
convert 6
Vector(6, 8)

我们可以看出, 上面代码没有立刻执行,而是当我们调用v.to(Vector)的时候,才会统一执行计算的。而且v的类型是View相关的。 而且,我们使用了slice对视图进行切割,实际执行的,只有slice标定的部分