4.For与Function进阶实战、Lazy的使用

一、for循环的进阶实战

1.for循环的变量可以有多个

for(i <- 1 to 2; j <- 1 to 3) println(i +" " + j )

这个for循环输出:

1 1
1 2
1 3
2 1
2 2
2 3

1.<-往左的箭头符号表示i会接受1 to 2这个集合里的值。每次循环集合的时候,把每次循环的元素赋值给i和j.

2.i和j不需要声明类型。scala会根据右侧的集合中具体元素的类型来自动进行类型推导。类型推导是scala中非常强大的内容。
2.for循环的条件守卫

for(i <- 1 to 2; j <- 1 to 3 if i != j) println(i +" " + j )

这个for循环输出:

1 2
1 3
2 1
2 3

我们可以在for循环的表达式里加入条件判断等。叫条件表达式的守卫。这种方式在spark中非常常见的。在正常的scala编程中也非常常见。当然条件表达式可以很复杂。

以上就是for循环相对进阶的部分,条件表达式的守卫比较重要。scala对开发的计算数据而言,提供了非常多的方便。

二、function的进阶实战

1.函数是有值的 Vs 匿名函数

    def addA(x : Int) = x + 100
    val add = (x : Int) => x + 200
    println(addA(2) + " " + add(5))

输出:

102 205

main方法不要求返回值时,返回Unit,也就是空值。函数有值的,如果不返回什么值,它就是空值。

所以,我们定义函数的时候,addA函数的参数是一个整数,函数是有值的,所以函数一般都会有个=,=右侧就是怎么对这个函数进行计算。传入x,返回的计算结果就是对x加100.

函数有值是scala中非常非常重要的特点,因为函数是有值的,每个函数执行的时候必然有一个结果,所以,函数可以作为函数的参数去传递。这个特点衍生了函数式编程中很多重要的技巧。实际上,我们进行一些复杂的算法的时候,根本不需要为函数命名。

  val add = (x : Int) => x + 200
       常量add  函数部分  ( 注意括号后面是箭头=>)

匿名函数是函数常见的一种状态,因为我们一般关心的是函数本身怎么做这件事情,对函数名字一般不关心。通过add这个常量的名称以及在其后加个括号,传入参数来调用

2.递归函数必须要声明返回值类型

上面addA函数并没有声明返回值,是因为scala编译器会根据右侧的表达式自动推断出函数的返回值。例如可以推断出addA返回值是整数。大多数情况下,都不需要声明函数的返回值类型,但是有一种特殊情况:递归调用。

def fac(n : Int) : Int = if(n <= 0) 1 else n * fac(n-1)
println(fac(9))
递归调用在scala以外的其他的系统或者框架的实现中,也可以不用声明函数的返回值。但是在scala中,必须指明递归调用函数的返回值。因为如果不指明递归调用函数的返回值的话,编译器会报错。

3.默认参数

 def combine(content : String , left : String = "[", right : String = "]") = left + content + right
 println(combine("I love spark!"))
 println(combine("I love spark!", "<<"))

输出:

[I love spark!]

<<I love spark!]

我们可以给函数参数提供默认值。如果传入第二个参数,肯定就会用我们传入的值覆盖掉原来默认的值。

4.函数的参数是可变的

   def connected(args : Int*) = {
      var result = 0
      for(arg <- args) result += arg
      result
    }
    println(connected(1,2,3,4,5))    

    println(connected(1,2,3,4,5,6))

 输出:

15

21

函数的参数可以输入多个,输入5个结果是15,输入6个结果是21.

以上就是从写代码的角度讲,函数常见的一些形态。

三、lazy的使用

lazy val file = Source.fromFile("E:\\ni.txt")
  
for(line <- file.getLines) println(line)

文件名不对,运行会报错

Exception in thread "main" java.io.FileNotFoundException: E:\ni.txt (系统找不到指定的文件。)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at scala.io.Source$.fromFile(Source.scala:90)
    at scala.io.Source$.fromFile(Source.scala:75)
    at scala.io.Source$.fromFile(Source.scala:53)
    at com.dt.scala.hello.ForFunctionLazy$.main(ForFunctionLazy.scala:35)
    at com.dt.scala.hello.ForFunctionLazy.main(ForFunctionLazy.scala)

但是如果注释掉下面一行

lazy val file = Source.fromFile("E:\\ni.txt")
println("scala")
//for(line <- file.getLines) println(line)

输出:scala

说明第一句和第二句都执行了,并没有报错。如果去掉lazy就报错了。说明变量或者常量加上lazy修饰,只有在第一次使用时,才会被实例化。

懒执行在数据处理方面,尤其对于同一个数据有很多迭代步骤的计算是非常重要的。因为延迟执行,我们可以看到更多的执行步骤,当你能看到一个计算的更多步骤时,进行优化的范围也就更大,优化力度也就会更好。而在spark大数据计算中,充分利用了这一点,lazy级别。


以上就是今天的内容,如果没有接触过scala,勉励大家把每个例子重复7次,基础就会很扎实,不要眼高手低,试一试就知道重复7次的效果了。感恩!


参考资料来源于 DT大数据梦工厂 Scala零基础实战经典第4课 由王家林老师讲解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值