第4讲:For与Function进阶实战、Lazy的使用

来源:互联网 发布:淘宝网卖妇婴用品 编辑:程序博客网 时间:2024/06/05 06:36

一、课程前导
DT大数据梦工厂的微信公众号是DT_Spark,每天都会有大数据实战视频发布,请您持续学习。
Scala 深入浅出实战经典(1-81讲)完整视频、PPT、代码下载:
百度云盘:http://pan.baidu.com/s/1c0noOt6
腾讯微云:http://url.cn/TnGbdC
360云盘:http://yunpan.cn/cQ4c2UALDjSKy  访问密码 45e2
Scala是最为重要的大数据语言,该视频每天还在持续跟新中,预计大约有140讲,请您根据上述视频彻底掌握Scala实战技术。

酷6:http://v.ku6.com/show/tGeUDYP9on3fGQvpwc40FA...html
51cto:http://edu.51cto.com/lesson/id-66566-show-2.html
优酷视频:http://v.youku.com/v_show/id_XMTI5NTQ3MDExNg==.html

最后,王家林老师个人的微信是18610086859

二、课程内容

注:下面的笔记源于王家林老师的第4讲:For与Function进阶实战、Lazy的使用视频和《快速Scala》书。
Scala 深入浅出实战经典
第4讲:For与Function进阶实战、Lazy的使用
1 for循环进阶
    可以看到以下代码i,j都没有进行声明类型,它可以根据右侧元素类型自动进行类型推导。
    在本次for循环中,有2个集合(1 to 2)有两个元素,通过左箭头 <- 把元素赋值给i 和j.
  for循环这里有个限制条件 i  != j, 当i=1时,符合条件的是j=2, 当i=2时, 符合条件的j是1。即 100*i+2 = 102, 200*2 +1 =201 ;
  def main(args: Array[String]): Unit = {
    for (i <- 1 to 2; j <- 1 to 2 if i != j)
      println((100 * i + j) + " ");
  }

运行代码得到如下结果:
102 
201

直接遍历字符序列:
var str = 0
for(ch <- "Hello")
 str += ch
2 function
1) 函数是有值的
Scala除了方法外还支持函数。方法对对象进行操作,函数不是。
要定义函数,你需要给出函数的名称、参数和函数体。语法如下:
def 函数名(值1:参数类型1) = 函数体
必须给出所有参数的类型。
只要函数不是递归的,就不需要指定返回类型。Scala编译器可以通过=符号右侧的表达式的类型推断出返回类型。
如果函数体需要多个表达式完成,可以用代码块。块中最后一个表达式的值就是函数的返回值。例如:
 def fac(n : Int) = {
  var i = 1
  for(i  <- 1 to n) r = r *i
  r
 }//r的值就是函数的值
在匿名函数中,return并不返回值给调用者,它只是跳出到包含它的带名函数中。可以把return当做是函数版的break语句,尽在需要时使用。
对于递归函数,必须指定返回类型。例如:
def fac(n : Int) : Int = if(n <= 0) 1 else n * fac(n - 1)


2) 匿名函数
   还有一种声明函数的方法,就是声明一个匿名函数,所谓匿名函数就是没有名字的函数,这点和js有点像,学过js的同学应该很快就理解了。
或者可以说把匿名函数复制给一个常量,通过常量调用匿名函数。
    通过 val add = (x: int) => x +100 ,来声明一个匿名函数,把 add指向这个匿名函数,匿名函数的实现使用右指针 =>指向实现的方法体。
通过 add(2)调用匿名函数。
def main(args: Array[String]): Unit = {
    val add = (x: Int) => x + 200
    println("The result from a val is " +  add(2))
 
}

 运行代码得到如下结果:
The result from a val is 202
 
 
3)函数的递归调用
递归调用实际上就是自己调用自己的函数,单要注意递归需要有退出循环的条件,否则就会造成“死循环”。
以下代码试求10的斐波那数,就是 10 * 9 * 8 * 7 * 6* 5 * 4 * 3 * 2 * 1 
 def main(args: Array[String]): Unit = {
    def fac(n:Int): Int = if (n <= 0) 1 else n * fac(n - 1)
     println("The result from  a fac is : " + fac(10) )
}
 

运行代码得到如下结果:
The result from a val is : 3628800

4) 有初始值的函数
在本例中输入3个参数, content, left, right. 其中content 是输入的内容, left和right是左右”护法“,呵呵,其实是左右连接符。
  object FunctionTest {
   def main(args : Array[String]):Unit = {
     def combine(content:String,left : String = "[",right : String = "]") = left + content + right
     println("the result from a combine is :" + combine("I love spark","@","@"))
   }
  }

运行代码得到如下结果:
the result from a combine is :@I love spark@

 
5)函数的参数是可变的
函数的输入值不是固定的,通过*表示可以输入多个参数,既可变参数。
object FunctionVarargs {
   def main(args : Array[String]) : Unit = {
     //定义可变参数累加函数
     def connected(args : Int*) = {
       var result = 0
       for(arg <- args){
         result += arg
       }
       result
     }
     //测试可变参数累加函数
     println("The result from a connected is :" + connected(1,2,3,4,5))
     println("The result from a connected is :" + connected(1,2,3,4,5,6))
   }
}

运行代码得到如下结果:
The result from a connected is : 15
The result from a connected is : 21

 
3 延迟加载lazy load
当val被声明为lazy时,它的初始化将被推迟,直到首次对它取值。例如:
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
可以把懒值当做是介入val和def的中间状态。对比如下定义: 
//在words被定义时即被取值
val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString

//在words被首次使用时取值
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString

//在每一次words被使用时取值
def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString

如果在E盘下不存在 users.txt, 使用 Source.fromFile()函数读取文件,就会报错抛出异常,
但是如果引用的常量前加上 lazy,它就不会报错。它只有在第一次被使用时,才被实例化。
注意:只要在下面的代码中不使用,就不会抛出异常。
import scala.io.Source
object LazyDemo {
  def main(args : Array[String]) : Unit = {
    val file = Source.fromFile("D:\\Hello.scala");
    for(line <- file.getLines())println(line)
  }
}

 
 附上学习视频,供大家参考:
 http://pan.baidu.com/s/1pJkRRZl

0 0
原创粉丝点击