Scala 流程控制

1. if else

1.1 单分支

语法结构:

if (expr) {
    expr为 true 时执行的语句
}

1.2 双分支

语法结构:

if (expr) {
    expr为 true 时执行的语句
} else {
    expr为 false 时执行的语句
}

1.3 多分支

语法结构:

if (expr1) {
    expr1为 true 时执行的语句
} else if (expr2) {
    expr2为 true 时执行的语句
}
	...
else {
    所有条件为 false 时执行的语句
}

1.4 嵌套分支

语法结构:

if (expr1) {
    if (expr2) {
        expr2为 true 时执行的语句
    } else {
        expr2为 false 时执行的语句
    }    
}

1.5 案例

案例:取出两个数的最大值

val a = 2
val b = 3
var max = if (a>b) a else b

Scala 中代码块的最后一行语句的输出作为代码块的返回值,当只有一行语句时,可写在一行,并省略 {}

利用 Java 的三目运算可写为 max = (a>b) ? a : b

⚠️ 注意:在 if else 中,如果 ifelse 分支的返回值不同时,需要使用两种类型的公共父类作为返回值类型,不知道时可以用 Any 类型。

if (a>b) : Any ={
    "abc"
} else {
    a
}

⚠️ 注意:如果没有 else 分支,else 分支默认返回 {} 的返回值 Unit ,则该 if else 的返回值类型可以用 Any 类型。

if (a>b) : Any ={
    "abc"
}

2. while、do while

whiledo while 表达式固定返回 Unit

2.1 while

语法结构:

while (expr) {
    expr为 true 时反复执行的语句
}

案例:打印50以内的斐波那契数列

var first = 0
var second = 1
var fibonacci = 0
while (fibonacci < 50) {
    println(fibonacci)
    first = second
    second = fibonacci
    fibonacci = first + second
}

2.2 do while

语法结构:

do {
    expr为 true 时反复执行的语句
}
while (expr)

案例:计算一个正整数的各位之和

var i = 53672
var sum = 0
do {
    sum += i % 10
    i /= 10
} while (i > 0)
println(sum) // 23

2.3 循环中断

Scala 中没有提供 break 和 continue 关键字,以便更好的适应函数式编程。

Scala 中可以使用控制循环条件、函数封装 + return 或 BreaksAPI

案例:判断一个整数是否含有偶位数

// 使用外部 Boolean 控制循环条件
var i = 67253
var nonEven = true
while (nonEven) {
    if (i % 10 % 2 == 0) {
        println("包含偶数位")
        nonEven = false
    }
    i /= 10
}
// 使用函数封装和 return 关键字
var i = 67253
def checkEven(n: Int) {
    var tmp = n
    while (true) {
        if (tmp % 10 % 2 == 0) {
            println("包含偶数位")
            return
        }
        tmp /= 10
    }
}
checkEven(i)
// 使用 BreaksAPI
Breaks.breakable {
    while (true) {
        if (i % 10 % 2 == 0) {
            println("包含偶数位")
            Breaks.break()
        }
        i /= 10
    }
}

3. for 循环

Scala 中的 for 叫做 for推导式。Scala 提供了一个功能强大的序列推导式。

语法结构:

for (enumerators) { 循环体 }

枚举器(enumerators):指的是一组以分号分隔的枚举器,枚举器可以由一个产生新变量的生成器(generator)以及一个守卫(guard)组成

生成器(generator):指的是一个形如 变量名 <- 集合 的表达式,生成器会在每次迭代时从 <- 右边的集合种去除一个元素赋给 <- 左边的变量

⚠️ 注意:for 推导式一行中有多个表达式时,需要用 ; 来隔断逻辑。当 for 推导式仅包含一个表达式时使用 (),当包含多行表达式时应当使用 {}

3.1 to、until

to 用于控制循环的范围,左闭右闭。

to 的用法:打印1到6的数

for (i <- 1 to 6){
    print(i)
}

until 也用于控制循环的范围,左闭右开。

unti 的用法:打印1到6的数

for (i <- 1 until 7){
    print(i)
}

3.2 守卫(guard)

守卫: 指的是一个形如 if expr 的表达式,当 expr 为 true 时执行循环体,为 false 时形如 Java 中的 continue 操作,跳过本次进入下一次循环。

guard 的用法:打印10以内的偶数

for (i <- 1 to 10 if i%2==0) println(i)

只有守卫中的条件成立,才会进入循环体

3.3 步长(by)

by 的用法:打印10以内的奇数

for (i <- 1 to 10 by 2) println(i)

3.4 嵌套循环

冒泡排序用到的就是两层 for 循环,多层 for 循环即为嵌套循环。前一层每循环依次,后一层的循环都要全部执行一遍。

嵌套循环的用法:

for (i <- 1 to 6; j <- 1 to 6){...}

等价于:

for (i <- 1 to 6){
    for (i <- 1 to 6){
        ...
    }
}

3.5 引入变量

引入变量的用法:

for (i <- 1 to 6; j = 6 - i){...}

等价于:

for (i <- 1 to 6){
 var j = 6 -i
 ...
}

3.6 获取返回值(yield)

对生成器中满足守卫条件的元素带入 for 的循环体中进行运算,最终所有的运算结果可利用 yield 收集到(Vector)集合中并返回

yield 的用法:获取字符串中所有字符的 ASCII 值

val str = "abc"
val ints = for (c <- str) yield c.asInstanceOf[Int]
println(ints)	// 输出: Vector(97, 98, 99)

4. 多重循环判断案例

案例:打印 99乘法口诀表!

// 居左排列
object CF_99 {
    def main(args: Array[String]): Unit = {
        for (i <- 1 to 9; j <- 1 to i) {
            print(s"${j}*${i}=${i * j}\t")
            if (i == j) println()
        }
    }
}
// 居右排列
object CF_99 {
    def main(args: Array[String]): Unit = {
        for (i <- 1 to 9) {
            if (i < 9) print("\t\t" * (9 - i))
            for (j <- 1 to i) {
                print(s"${j}*${i}=${i * j}\t")
                if (i == j) println()
            }
        }
    }
}

 


❤️ END ❤️
上一篇:第二章 变量和数据类型


下一篇:Spark记录(一):Spark全景概述