Spark大数据处理——掌握Scala内建控制结构

零、本节学习目标

  1. 掌握条件表达式
  2. 掌握各种循环
  3. 理解流间变量绑定
  4. 掌握yield语句的使用
  5. 掌握异常处理语句
  6. 了解match语句的使用
  7. 理解变量作用域

 Scala提供的控制结构并不算多,因为在函数式编程中,可以自己开发出各种功能的控制结构,所以Scala提供的原生控制结构仅仅够用为止。

一、条件表达式

(一)语法格式

1. if (条件) 值1 else 值2
 

(二)执行情况

  • 条件为真,结果是值1;条件为假,结果是值2。如果if和else的返回结果同为某种类型,那么条件表达式结果也是那种类型,否则就是Any类型
  • Scala的条件表达式有点类似于Java的条件运算符

(三)案例演示

任务1、根据输入值的不同进行判断

 当然也可以在一个表达式中进行多次判断

 可以将上述条件表达式改造成嵌套的选择结构,可读性倒是提高了,但是简洁性降低了

 

任务2、编写Scala程序,判断奇偶性

  • 打开Scala项目ScalaDemo,创建net.cl.day02包,在包里创建Example01对象
    package net.cl.day02
    
    import scala.io.StdIn
    
    /**
     * 功能:判断奇偶性
     * 作者:cl
     * 日期:2023年02月22日
     */
    object Example01 {
      def main(args: Array[String]): Unit = {
        print("n = ")
        val n = StdIn.readLine.toInt
        if (n % 2 == 0)
          println(n.toString + "是偶数~")
        else
          println(n.toString + "是奇数~")
      }
    }
    

    运行程序,查看运行结果: 

     

  • 利用if结构具有返回值的特性,改写程序成为函数式风格(创建Example02)

package net.cl.day02

object Example02 {

  import scala.io.StdIn
    def main(args: Array[String]): Unit = {
      print("n = ")
      val n = StdIn.readLine.toInt
      val result = if (n % 2 == 0)
        n.toString + "是偶数~"
      else
        n.toString + "是奇数~"
      println(result)
    }

}

运行程序,查看运行结果:

二、块表达式

(一)语法格式

{语句组} 

  • 块表达式为包含在符号“{}”中的语句块

(二)执行情况

  • 需要注意的是,Scala中的返回值是最后一条语句的执行结果,而不需要像Java一样单独写return关键字。如果表达式中没有执行结果,就返回一个Unit对象,类似Java中的void

(三)案例演示

  • 语句块最后一句的值就是整个块表达式的结果

  • 语句块最后一句没有执行结果,那么块表达式结果就是Unit

    三、for循环

    (一)单重for循环

    1、语法格式

 for (变量 <- 集合或数组 (条件)) {
     语句组
}

2、执行情况

  • 表示将集合或数组中的每一个值循环赋给一个变量

3、案例演示

任务1:输出1到10

  • 两种方式实现,一种使用Range类,一种使用to运算符

  • Range(a, b): 从a到b,不包含b,跟Python里的range函数一样,含头不含尾

  • 1 to 10表示将1到10的所有值组成一个集合,且包括10。若不想包括10,则可使用关键字until

  • 打印字符直角三角形

  • 利用map函数产生每行星号构成的向量,然后利用foreach函数循环输出

  • 利用双重循环与流间变量,这个是Scala语言特有的东西

任务2、遍历字符串,输出每个字符

  • 方法一、按索引取字符串的每个字符(传统for循环)

  • 方法二:将字符串看作一个由多个字符组成的集合(增强for循环) 

任务3、计算 1 + 2 + 3 + … + 100

  • 注意sum必须定义为var型变量
  • 利用集合的归并方法来求和最简单

 

任务4、输出列表内的偶数(过滤)

  • 采用三种方法来实现

 任务5、输出全部两位素数

1:for (n <- 10 to 100; if !(n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0))  print(n.toString + " ")

2;(10 to 100).filter(n => !(n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0))

 

(二)嵌套for循环

1、语法格式

  • 传统格式
    for (变量1 <- 集合或数组(条件))
        for (变量2 <- 集合或数组(条件)) {
           语句组
        }
    }
    

  • 特有格式
    for (变量1 <- 集合或数组; 变量2 <- 集合或数组 (条件)) {
       语句组
    }
    

2、案例演示

任务1、打印九九表

方法一、采用双重循环来实现

  • net.cl.day03包里创建Example02对象(Example01在后面,顺序不对,注意看清楚)
    package net.cl.day03
    
    object Example02 {
    
    
      /**
       * 功能:双重循环打印九九表
       * 作者:cl
       * 日期:2023年02月27日
       */
        def main(args: Array[String]): Unit = {
          for (i <- 1 to 9) {
            for (j <- 1 to i) {
              print(i.toString + "×" + j + "=" + (i * j) + "\t")
            }
            println()
          }
        }
    
    
    
    
    }
    
  • 运行程序,查看结果

方法二、采用单重循环来实现

  • net.cl.day03包里创建Example03对象
    package net.cl.day03
    
    object Example03 {
    
      /**
       * 功能:单重循环打印九九表
       * 作者:cl
       * 日期:2023年02月27日
       */
        def main(args: Array[String]): Unit = {
          for (i <- 1 to 9; j <- 1 to i) {
            print(i.toString + "×" + j + "=" + (i * j) + "\t")
            if (j == i) println()
          }
        }
    
    
    }
    
  • 运行程序,查看结果

方法三、采用单重循环与流间变量绑定来实现

package net.cl.day03

object Example04 {
  /**
   * 功能:单重循环与流间变量绑定打印九九表
   * 作者:cl
   * 日期:2023年02月27日
   */
    def main(args: Array[String]): Unit = {
      for (i <- 1 to 9; j <- 1 to i; sep = if (j == i) "\n" else "\t") {
        print(i.toString + "×" + j + "=" + (i * j) + sep)
      }
    }
}
  • net.cl.day03包里创建Example04对象
  • 在for循环头里sep = if (i == j) "\n" else "\t"就是流间变量绑定
  • 运行程序,查看结果

 方法四、采用单重循环、流间变量与yield来实现
for循环语句本身的返回值是Unit类型,无论在循环体中返回什么都是无效的,最终得到的都是Unit的值,但是可以在循环中的循环条件和循环体之间加上yield关键字,那么就可以将循环体产生的返回值组成数组进行返回。
在net.cl.day03包里创建Example01对象

package net.cl.day03

object Example01 {

  /**
   * 功能:采用单重循环、流间变量与yield打印九九表
   * 作者:cl
   * 日期:2023年02月27日
   */
    def main(args: Array[String]): Unit = {
      val list = for (i <- 1 to 9; j <- 1 to i; sep = if (j == i) "\n" else "\t")
        yield i.toString + "×" + j + "=" + (i * j) + sep
      list.foreach(print)
    }


}

运行结果如下:

任务2、去掉对角线

  • 一个三阶方阵,单元格的值是行号与列号的乘积,去掉对角线,输出剩余元素
  • 方法一、传统双重循环(创建Example05对象)
    package net.cl.day03
    
    object Example05 {
    
      /**
       * 功能:去掉对角元素
       * 作者:cl
       * 日期:2023年02月27日
       */
        def main(args: Array[String]): Unit = {
          for (i <-1 to 3) {
            for (j <- 1 to 3) {
              if (i != j)
                print((i * j).toString + "\t")
              else
                print("\t")
            }
            println()
          }
        }
    
    }
    
  • 运行程序,查看结果

  • 方法二、特有双重循环

    package net.cl.day03
    
    object Example07 {
    
      /**
       * 功能:去掉对角线元素(双重循环)
       * 作者:cl
       * 日期:2023年03月02日
       */
        def main(args: Array[String]): Unit = {
          for (i <- 1 to 3; j <- 1 to 3; sep = if (i == j) "\t" else (i * j).toString + "\t") {
            print(sep)
            if (j == 3) println()
          }
        }
    
    
    }
    
  • 运行程序,查看结果

  • 方法三:采用两个流间变量和yield

    package net.cl.day03
    
    object Example08 {
    
      /**
       * 功能:去掉对角线元素
       * 作者:cl
       * 日期:2023年03月02日
       */
        def main(args: Array[String]): Unit = {
          val list = for (i <- 1 to 3; j <- 1 to 3; sep = if (j==3) "\n" else "\t";
                          str = if (i != j) (i * j).toString + sep else " " + sep) yield str
          list.foreach(print)
        }
    
    
    }
    
  • 运行程序,查看结果

四、条件循环

(一)while循环

1、语法格式

  • Scala的while循环与Java类似

while(条件) {   
   循环体
}

2、案例演示

任务1、计算1+ 2 + 3 + … + 100

  • net.cl.day03包里创建Example10对象

  • 采用函数式风格来写代码,递归函数来实现求和,注意:此处sum是常量
  • net.huawei.day02包里创建Example10_对象
    package net.cl.day03
    
    object Example10 {
    
      /**
       * 功能:等差数列求和
       * 作者:cl
       * 日期:2023年03月02日
       */
        def mx(n: Int, sum: Int): Int = {
          if (n > 0) mx(n - 1, sum + n) else sum
        }
    
        def main(args: Array[String]): Unit = {
          println("1 + 2 + 3 + ... + 100 = " + mx(100, 0))
        }
    
    
    }
    

  • 运行程序,查看结果

  • 普通版:

    package net.cl.day03
    
    object Example12 {
    
      /**
       * 功能:等差数列求和
       * 作者:cl
       * 日期:2023年03月02日
       */
        def main(args: Array[String]): Unit = {
          var sum = 0
          var i = 1
          do {
            sum = sum + i
            i = i + 1
          } while (i <= 100)
          println("1 + 2 + 3 + ... + 100 = " + sum)
        }
    }
    

  • 运行程序,结果如下

任务2、打印全部水仙花数

  • 所谓水仙花数,是指等于其各位数字立方和的三位数。
  • 首先求n的个位数:n % 10
    然后要将三位数变成两位数:n = n / 10;
    对于新的两位数n,又求它的个位数:n % 10
    然后要将两位数变成一位数:n = n / 10;

  • net.cl.day02包里创建Example11对象

    package net.cl.day03
    
    object Example11 {
    
      /**
       * 功能:打印水仙花数
       * 作者:cl
       * 日期:2023年03月02日
       */
        def main(args: Array[String]): Unit = {
          for (n <- 100 to 999) {
            val p1 = n % 10 // 个位数
            val p2 = n / 10 % 10 // 十位数
            val p3 = n / 100 // 百位数
            if (n == p1 * p1 * p1 + p2 * p2 * p2 + p3 * p3 * p3)
              println(n.toString + " = " + p3 + "^3 + " + p2 + "^3 + " + p1 + "^3")
          }
        }
    
    
    }
    

  • 运行程序,查看结果

五、异常处理

(一)异常处理概述

  • Scala中继承了Java的异常机制,提供了程序中产生意外情况时处理的机制,抛出异常的过程和Java中基本一致,通过throw关键字进行:throw XxxException(),一旦抛出可以当场捕获处理或接着向上抛,捕获异常是通过 try-catch-finally来实现的。

(二)案例演示

任务:演示try-catch-finally

  • try-catch-finally是有返回值的:如果没有异常就是try语句的返回值,如果有异常就是catch语句的返回值。注意不会是finally的返回值,finally即使有返回值,也会被抛弃,这点和Java是不同的。
  • net.cl.day03包里创建Example13对象
    package net.cl.day03
    
    
      import java.io.IOException
    
      /**
       * 功能:演示异常处理
       * 作者:cl
       * 日期:2023年03月02日
       */
      object Example13 {
        def main(args: Array[String]): Unit = {
          var message = ""
          val result = try {
            mx() // 调用方法,会抛出异常
            "恭喜,程序执行正常~"
          } catch {
            case e: NullPointerException => "空指针异常"
            case e: IOException => "呵呵,这是I/O异常~"
            case e: RuntimeException => "哈哈,这是运行时异常~"
            case e: Exception => "管它呢,反正是异常~"
          } finally {
            message = "程序到此为止~"
            "无论是否有异常,都会执行finally里的语句~"
          }
          println(result)
          println(message)
        }
    
        def mx(): Unit = {
          throw new RuntimeException("故意抛出一个运行时异常~")//注释掉mx()方法李的语句就可以运行成功
      }
    
    
    }
    
  • 执行程序,查看结果(此时有异常,result取的是catch里的返回值 - 哈哈,这是运行时异常~,finally语句块执行了的,因此message可以打印出来 - 程序到此为止!

  • 注释掉mx()方法里的语句

  • 执行程序,查看结果(此时有异常,result取的是try里的返回值 - 恭喜,程序执行正常! 

(二)案例演示

任务:给城市下评语

  • net.cl.day03包里创建Example14对象
    package net.cl.day03
    
    
      import scala.io.StdIn
    
      /**
       * 功能:给城市下评语
       * 作者:cl
       * 日期:2023年03月02日
       */
      object Example14 {
        def main(args: Array[String]): Unit = {
          print("输入城市:")
          val city = StdIn.readLine()
          val comment = city match {
            case "北京" => "是伟大的首都~"
            case "上海" => "是神奇的魔都~"
            case "广州" => "是迷人的妖都~"
            case "乐山" => "是甜皮鸭的家~"
            case _ => "是普通的城市~"
          }
          println(city + comment)
        }
    
    }
    

     

七、补充案例

任务:评定成绩等级

1、编写符合函数式编程风格的Sala程序

  • net.cl.day03包里创建Example17对象
    package net.cl.day03
    
    
    import scala.io.StdIn
    
    /**
     * 功能:成绩等级评定(采用函数式风格)
     * 作者:cl
     * 日期:2023年03月02日
     */
    object Example17 {
      def main(args: Array[String]): Unit = {
        print("score = ")
        val score = StdIn.readLine().toInt
    
        val comment = if (score > 100) {
          "超出范围"
        } else if (score >= 90) {
          "优秀"
        } else if (score >= 80) {
          "良好"
        } else if (score >= 70) {
          "中等"
        } else if (score >= 60) {
          "及格"
        } else if (score >= 0) {
          "不及格"
        } else {
          "超出范围"
        }
    
        println("评语:" + comment)
      }
    
    
    }
    
  • 运行程序,查看结果

  •  函数式风格的程序有几个特点

if结构像函数一样有返回值
if结构里除了传入参数score之外,没有别的变量。
-if结构里没有与外界交流,比如输入或输出或网络连接或读取文件之类。
函数式编程是为了处理计算,不考虑系统的读写(I/O)。
函数式编程强调没有副作用(指的是函数内部与外部互动,产生运算以外的其它结果)。函数要求独立,只返回一个值,没有其它行为,尤其不能修改外部变量的值

2、非函数式风格的程序

package net.cl.day03



  import scala.io.StdIn

  /**
   * 功能:成绩等级评定(采用非函数式风格)
   * 作者:cl
   * 日期:2023年03月02日
   */
  object Example18 {
    def main(args: Array[String]): Unit = {
      print("score = ")
      val score = StdIn.readLine().toInt

      var comment = ""
      if (score > 100) {
        comment = "超出范围"
      } else if (score >= 90) {
        comment = "优秀"
      } else if (score >= 80) {
        comment = "良好"
      } else if (score >= 70) {
        comment = "中等"
      } else if (score >= 60) {
        comment = "及格"
      } else if (score >= 0) {
        comment = "不及格"
      } else {
        comment = "超出范围"
      }

      println("评语:" + comment)
    }
}

 虽然处理结果跟上面那个程序一样,但是并不符合函数式编程风格。因为if结构有副作用,修改了if结构之外的变量comment的值

package net.cl.day03


  import scala.io.StdIn

  /**
   * 功能:成绩等级评定(采用非函数式风格)
   * 作者:华卫
   * 日期:2023年03月01日
   */
  object Example19 {
    def main(args: Array[String]): Unit = {
      print("score = ")
      val score = StdIn.readLine().toInt

      if (score > 100) {
        println("评语:超出范围")
      } else if (score >= 90) {
        println("评语:优秀")
      } else if (score >= 80) {
        println("评语:良好")
      } else if (score >= 70) {
        println("评语:中等")
      } else if (score >= 60) {
        println("评语:及格")
      } else if (score >= 0) {
        println("评语:不及格")
      } else {
        println("评语:超出范围")
      }
    }


}

不符合函数式编程风格。因为if结构有副作用,有写操作

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值