第 4 章 流程控制 4.1 分支控制 if-else 让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支
4.1.1 单分支1)基本语法
说明:当条件表达式为 ture 时,就会执行{ }的代码。
2)案例实操 1 2 3 if (age >= 18 ){ println("成年" ) }
4.1.2 双分支 1)基本语法 1 2 3 4 5 if (条件表达式) { 执行代码块 1 } else { 执行代码块 2 }
2)案例实操 1 2 3 4 5 if (age >= 18 ){ println("成年" ) } else { println("未成年" ) }
4.1.3 多分支 1)基本语法 1 2 3 4 5 6 7 8 9 10 11 if (条件表达式 1 ) { 执行代码块 1 } else if (条件表达式 2 ) { 执行代码块 2 } …… else {执行代码块 n }
2)案例实操 1 2 3 4 5 6 7 8 9 10 11 if (age <= 6 ){ println("童年" ) } else if (age < 18 ){ println("青少年" ) } else if (age < 35 ){ println("青年" ) } else if (age < 60 ){ println("中年" ) } else { println("老年" ) }
(2)需求 2:Scala 中 if else 表达式其实是有返回值的,具体返回值取决于满足条件的代码体的最后一行内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 val result: String = if (age <= 6 ){ println("童年" ) "童年" } else if (age < 18 ){ println("青少年" ) "青少年" } else if (age < 35 ){ println("青年" ) "青年" } else if (age < 60 ){ println("中年" ) "中年" } else { println("老年" ) "老年" } println("result: " + result)
(3)需求 3:Scala 中返回值类型不一致,取它们共同的祖先类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 val result: Any = if (age <= 6 ){ println("童年" ) "童年" } else if (age < 18 ){ println("青少年" ) "青少年" } else if (age < 35 ){ println("青年" ) age } else if (age < 60 ){ println("中年" ) age } else { println("老年" ) age } println("result: " + result)
(4)需求 4:Java 中的三元运算符可以用 if else 实现
如果大括号{}内的逻辑代码只有一行,大括号可以省略。如果省略大括号,if 只对最近的一行逻辑代码起作用。
1 2 3 4 5 6 val res: String = if (age >= 18 ){ "成年" } else { "未成年" } val res2 = if (age >= 18 ) "成年" else "未成年"
4.2 嵌套分支在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层。分支外面的分支结构称为外层分支。嵌套分支不要超过 3 层。
1)基本语法 1 2 3 4 5 6 7 if (){ if (){ }else { } }
2)案例实操 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 if (age >= 18 ){ println("成年" ) if (age >= 35 ){ if (age >= 60 ){ println("老年" ) } else { println("中年" ) } } else { println("青年" ) } } else { println("未成年" ) if (age <= 6 ){ println("童年" ) } else { println("青少年" ) }
4.3 Switch 分支结构
4.4 For 循环控制 Scala 也为 for 循环这一常见的控制结构提供了非常多的特性,这些 for 循环的特性被称为 for 推导式或 for 表达式。
4.4.1 范围数据循环(To)定义一个循环变量,给他赋一个初值,还要定义每次循环之后这个循环变量怎么改变,还得定义一个推出循环的标记。首先比较繁琐,另外初值是从0开始的,特别是取数组的下标索引都是从0开始。这样就涉及到一个退出循环的标记是小于还是小于等于呢。当前的边界到底取还是不取,往往让我们感到麻烦。总要想一想才能得到结论,容易出错。所以Scala设计的时候就想到Java这些特点都不要,让程序员使用for没那么多困惑,用最简单的方式实现我们的功能即可。
比如带着当前的编号输出10次Hello World。那只要遍历一个1-10的范围作为编号即可。
1)基本语法 1 2 3 4 for (i <- 1 to 3 ){ print(i + " " ) } println()
i 表示循环的变量,<- 规定 to
i 将会从 1-3 循环,前后闭合
2)案例实操 1 2 3 4 5 6 7 8 for (i <- 1 to 10 ){ println(i + ". hello world" ) } for (i: Int <- 1. to(10 )){ println(i + ". hello world" ) }
4.4.2 范围数据循环(Until)1)基本语法 1 2 3 4 for (i <- 1 until 3 ) { print(i + " " ) } println()
2)案例实操 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 for (i <- 1 to 10 ){ println(i + ". hello world" ) } for (i: Int <- 1. to(10 )){ println(i + ". hello world" ) } for (i <- 1 until 10 ){ println(i + ". hello world" ) }
1 2 3 4 5 6 7 8 9 for (i <- Array (12 , 34 , 53 )){ println(i) } for (i <- List (12 , 34 , 53 )){ println(i) } for (i <- Set (12 , 34 , 53 )){ println(i) }
4.4.3 循环守卫 1)基本语法 1 2 3 4 for (i <- 1 to 3 if i != 2 ) { print(i + " " ) } println()
1 2 3 4 5 for (i <- 1 to 3 ){ if (i != 2 ) { print(i + " " ) } }
2)案例实操 需求:输出 1 到 10 中,不等于 5 的值
1 2 3 4 5 6 7 8 9 10 for (i <- 1 to 10 ){ if (i != 5 ){ println(i) } } for (i <- 1 to 10 if i != 5 ){ println(i) }
4.4.4 循环步长1)基本语法 1 2 3 for (i <- 1 to 10 by 2 ) { println("i=" + i) }
说明:by 表示步长
2)案例实操 需求:输出 1 到 10 以内的所有奇数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 for (i <- 1 to 10 by 2 ){ println(i) } 1 3 5 7 9 println("-------------------" ) for (i <- 13 to 30 by 3 ){ println(i) } 13 16 19 22 25 28 println("-------------------" ) for (i <- 30 to 13 by -2 ){ println(i) } 30 28 26 24 22 20 18 16 14 for (i <- 10 to 1 by -1 ){ println(i) } 10 9 8 7 6 5 4 3 2 1 println("-------------------" ) for (i <- 1 to 10 reverse){ println(i) } 10 9 8 7 6 5 4 3 2 1 println("-------------------" ) for (data <- 1.0 to 10.0 by 0.3 ){ println(data) } 1.0 1.3 1.6 1.9000000000000001 2.2 2.5 2.8 3.0999999999999996 3.3999999999999995 3.6999999999999993 3.999999999999999 4.299999999999999 4.599999999999999 4.899999999999999 5.199999999999998 5.499999999999998 5.799999999999998 6.099999999999998 6.399999999999998 6.6999999999999975 6.999999999999997 7.299999999999997 7.599999999999997 7.899999999999997 8.199999999999998 8.499999999999998 8.799999999999999 9.1 9.4 9.700000000000001 10.000000000000002
4.4.5 嵌套循环 1)基本语法 1 2 3 for (i <- 1 to 3 ; j <- 1 to 3 ) { println(" i =" + i + " j = " + j) }
说明:没有关键字,所以范围后一定要加;来隔断逻辑
2)基本语法 上面的代码等价
1 2 3 4 5 for (i <- 1 to 3 ) { for (j <- 1 to 3 ) { println("i =" + i + " j=" + j) } }
4.4.6 引入变量1)基本语法 1 2 3 for (i <- 1 to 3 ; j = 4 - i) { println("i=" + i + " j=" + j) }
说明:
1 2 3 4 5 6 for { i <- 1 to 3 j = 4 - i } { println("i=" + i + " j=" + j) }
2)案例实操 上面的代码等价于
1 2 3 4 for (i <- 1 to 3 ) { var j = 4 - i println("i=" + i + " j=" + j) }
需求:输出九九乘法表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 object Test03_Practice_MulTable { def main (args: Array [String ]): Unit = { for (i <- 1 to 9 ){ for (j <- 1 to i){ print(s"$j * $i = ${i * j} \t" ) } println() } for (i <- 1 to 9 ; j <- 1 to i){ print(s"$j * $i = ${i * j} \t" ) if (j == i) println() } } }
需求:打印输出一个九层妖塔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 object Test04_Practice_Pyramid { def main (args: Array [String ]): Unit = { for (i <- 1 to 9 ){ val stars = 2 * i - 1 val spaces = 9 - i println(" " * spaces + "*" * stars) } for (i <- 1 to 9 ; stars = 2 * i - 1 ; spaces = 9 - i){ println(" " * spaces + "*" * stars) } for (stars <- 1 to 17 by 2 ; spaces = (17 - stars) / 2 ){ println(" " * spaces + "*" * stars) } } }
4.4.7循环返回值 1)基本语法 1 2 val res = for (i <- 1 to 10 ) yield iprintln(res)
说明:将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字。
注意:开发中很少使用。
2)案例实操 需求:将原数据中所有值乘以 2,并把数据返回到一个新的集合中。
1 2 3 4 5 6 7 8 9 10 object TestFor { def main (args: Array [String ]): Unit = { var res = for (i <-1 to 10 ) yield { i * 2 } println(res) } } Vector (2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 , 20 )
4.4.8 倒序打印
需求:倒序打印 10 到 1
1 2 3 for (i <- 1 to 10 reverse){ println(i) }
4.5 While 和 do..While循环控制 While 和 do..While 的使用和 Java 语言中用法相同。
大数据场景下会使用并行处理,每一个并行出来的代码块都会影响全局变量,显然最后的结果就不正确了,所以在Scala中为了大数据的应用场景设计出来的语言,其实不推荐使用while循环 甚至真正的函数式编程语言是没有变量的,不要说while循环,连for循环都没有。没有循环,都是使用递归来实现循环类似的功能。
4.5.1 While 循环控制 1)基本语法 1 2 3 4 5 循环变量初始化 while (循环条件) { 循环体(语句) 循环变量迭代 }
说明:
2)案例实操 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 object Test05_WhileLoop { def main (args: Array [String ]): Unit = { var a: Int = 10 while (a >= 1 ){ println("this is a while loop: " + a) a -= 1 } var b: Int = 0 do { println("this is a do-while loop: " + b) b -= 1 } while (b > 0 ) } }
4.5.2 do..while 循环控制 1)基本语法 1 2 3 4 5 6 循环变量初始化; do { 循环体(语句) 循环变量迭代 } while (循环条件)
说明
循环条件是返回一个布尔值的表达式
do..while 循环是先执行,再判断
2)案例实操 1 2 3 4 5 var b: Int = 0 do { println("this is a do-while loop: " + b) b -= 1 } while (b > 0 )
4.6 循环中断 1)基本说明 Scala 内置控制结构特地去掉了 break和 continue,是为了更好的适应函数式编程 ,推荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable控制结构来实现 break 和 continue 功能。
2)案例实操 需求 1:采用异常的方式退出循环
1 2 3 4 5 6 7 8 9 10 try { for (i <- 0 until 5 ){ if (i == 3 ) throw new RuntimeException println(i) } } catch { case e: Exception => }
需求 2:采用 Scala 自带的函数,退出循环
1 2 3 4 5 6 7 8 Breaks .breakable( for (i <- 0 until 5 ){ if (i == 3 ) Breaks .break () println(i) } )
需求 3:对 break 进行省略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import scala.util.control.Breaks ._object TestBreak { def main (args: Array [String ]): Unit = { breakable { for (elem <- 1 to 10 ) { println(elem) if (elem == 5 ) break } } println("正常结束循环" ) } } breakable( for (i <- 0 until 5 ){ if (i == 3 ) break () println(i) } )
需求 4:循环遍历 10 以内的所有数据,奇数打印,偶数跳过(continue)
1 2 3 4 5 6 7 8 9 10 11 object TestBreak { def main (args: Array [String ]): Unit = { for (elem <- 1 to 10 ) { if (elem % 2 == 1 ) { println(elem) } else { println("continue" ) } } } }