循环结构
Scala同样提供了对程序流程控制的语法。Scala中的程序流程控制结构虽然与Java类似,但也有自己的一些独特的方法。
循环结构
经常地,我们需要遍历集合中的元素,或者对集合中的每个元素进行操作,或者从现有集合创建一个新集合,这就需要用到循环结构。Scala拥有与Java和C++相同的while和do-while循环。
下面是使用while的循环语句:
var sum = 0 var i = 1 while(i < 11) { sum += i i += 1 } sum i
输出结果如下:
sum: Int = 0 i: Int = 1 res26: Int = 55 res27: Int = 11
请看下面的示例代码:
// while语句 var i = 1 while (i <= 5) { println("hello") i = i + 1 } //输出1到10的偶数 //方法1 var j = 1 while (j <= 10) { //如果j是偶数 if (j % 2 == 0) { println(j) } j = j + 1 } //方法2 var k = 2 while (k <= 10) { println(k) k = k + 2 }
输出结果如下:
i: Int = 1 hello hello hello hello hello j: Int = 1 2 4 6 8 10 k: Int = 2 2 4 6 8 10
Scala 也有do-while循环,它和while循环类似,只是检查条件是否满足在循环体执行之后检查。例如:
var sum = 0 var i = 1 do { sum += i i += 1 } while(i <= 10) println("1+...+10=" + sum)
Scala也提供了for循环和foreach方法。下面的代码使用for-each循环来遍历数组:
val a = Array("apple", "banana", "orange") for (e <- a) println(e) for (e <- a) { val s = e.toUpperCase println(s) }
可以在for表达式内部定义变量,然后,可以在for表达式的body中重用这些变量,这称为"变量绑定"。如下代码所示:
val books = Array("Scala从入门到精通", "Groovy从入门到精通", "Java从入门到精通", "24小时精通Scala", "24小时精通Java") for {book <- books bookVa1 = book.toUpperCase() bookVa2 = book.toLowerCase() } println(bookVa1 + "," + bookVa2)
注意to和until的区别。until不包含上边界值,而to包含上边界值。请看下面的代码:
object Hello { def main(args:Array[String]){ for(i <- 1 until 10){ print(i + " ") } println() for(i <- 1 to 10){ print(i + " ") } } }
输出结果如下所示:
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10
【示例】遍历数组。
// 声明数组 var myList = Array(1.9, 2.9, 3.4, 3.5) // 输出所有数组元素 for ( x <- myList ) { println( x ) } // 计算数组所有元素的总和 var total = 0.0; for ( i <- 0 to (myList.length - 1)) { total += myList(i); } println("总和为 " + total); // 查找数组中的最大元素 var max = myList(0); for ( i <- 1 to (myList.length - 1) ) { if (myList(i) > max) max = myList(i); } println("最大值为 " + max);
注:实际上可以用高阶函数,更加简洁地遍历数组(集合)。例如:
// 遍历 var myList = Array(1.9, 2.9, 3.4, 3.5) myList.map(println) myList.foreach(println)
【示例】登录用户名密码的游戏:三次机会,从控制台输入输入用户名密码,如果成功登录,返回登录成功,失败,则反馈错误信息!如下:
import scala.io.StdIn object Example02 { def main(args: Array[String]): Unit = { val dbUser = "mm" val dbPassword = "1234" var count = 3 while(count > 0) { val username = StdIn.readLine("请输入账号:") val userpwd = StdIn.readLine("请输入密码:") if(username == dbUser && userpwd == dbPassword) { println(s"登陆成功,欢迎$username!") count = 0 } else { count -= 1 println("用户名或密码错误!您还有<$count>次机会!") } } } }
在循环中使用if条件过滤值
在Scala中,还可以使用if子句来在遍历条目时添加过滤支持。例如,在下面的示例中,将水果名称长度超过2的过滤掉。
object demo { def main(args: Array[String]): Unit = { println("在for循环中使用if条件过滤值") val fruits = List("苹果","香蕉","桃子","猕猴桃","凤梨") for(fruit <- fruits if fruit.length<3){ println(fruit) } } }
输出结果如下所示:
在for循环中使用if条件过滤值 苹果 香蕉 桃子 凤梨
在for循环中使用if条件过滤值,并使用yield关键字返回结果。
object demo04 { def main(args: Array[String]): Unit = { println("\n在for循环中使用if条件过滤值,并使用yield关键字返回结果") val fruits = List("苹果","香蕉","桃子","猕猴桃","凤梨","杏","无籽西瓜","水晶葡萄") val fruitTwo = for { fruit <- fruits if fruit.length == 3 || fruit.length == 4 } yield fruit println(s"过滤后的水果有 = $fruitTwo") } }
输出结果如下所示:
在for循环中使用if条件过滤值,并使用yield关键字返回结果 过滤后的水果有 = List(猕猴桃, 无籽西瓜, 水晶葡萄)
在for循环中可以使用分号 (;) 来设置多个区间,它将迭代给定区间所有的可能值。以下示例代码演示了两个区间的循环实例:
for( a <- 1 to 3; b <- 1 to 3){ print( "a = " + a ) println( ", b = " + b ) }
输出结果如下所示:
a = 1, b = 1 a = 1, b = 2 a = 1, b = 3 a = 2, b = 1 a = 2, b = 2 a = 2, b = 3 a = 3, b = 1 a = 3, b = 2 a = 3, b = 3
【示例】遍历二维数组。
// 处理多维数组 var myMatrix = Array.ofDim[Int](3,3) // 创建矩阵 for (i <- 0 to 2) { for ( j <- 0 to 2) { myMatrix(i)(j) = j; } } // 打印二维阵列 for (i <- 0 to 2; j <- 0 to 2) { print(" " + myMatrix(i)(j)); if(j==2) println() } println("-------------------") // 多维数组 val array = Array.ofDim[Int](2, 2) array(0)(0) = 0 array(0)(1) = 1 array(1)(0) = 2 array(1)(1) = 3 for { i <- 0 to 1 j <- 0 to 1 } println(s"($i)($j) = ${array(i)(j)}")
执行结果如下:
0 1 2 0 1 2 0 1 2 ------------------ (0)(0) = 0 (0)(1) = 1 (1)(0) = 2 (1)(1) = 3
【示例】编程输出九九乘法表。
// 九九乘法表 1 for(i <- 1 to 9) { for(j <- 1 to i){ var ret = i * j print(s"$i*$j=$ret\t") } println() } // 九九乘法表 2 for(i <- 1 to 9; j <- 1 to i) { var ret = i * j print(s"$i*$j=$ret\t") if(i == j) { println } }
输出结果如下:
1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 -------------- 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
中断循环
Scala并没有提供break或continue语句来退出循环。那么如果需要break时我们该怎么做呢?有如下几个选项:
- 1) 使用Boolean型的控制变量。
- 2) 使用嵌套函数——可以从函数当中return。
- 3) 使用Breaks对象中的break方法。
break方法使用如下面的示例代码所示:
import scala.util.control.Breaks._ var n = 15 breakable { for(c <- "Spark Scala Storm") { if(n == 10) { println() break } else { print(c) } n -= 1 } }
输出内容如下:
import scala.util.control.Breaks._ n: Int = 15 Spark
循环中使用计数器
使用for-each循环有一个缺点,就是无法获取当前索引值。为此,可使用循环计数器。请看以下的代码:
val a = Array("张三","李四","王老五") // 循环计数 for (i <- 0 until a.length) { println(s"$i:${a(i)}") }
输出结果如下:
0:张三 1:李四 2:王老五
Scala集合还提供了一个zipWithIndex方法可用于创建循环计数器:
for ((e, index) <- a.zipWithIndex) { println(s"$index: $e") }
输出结果如下:
0:张三 1:李四 2:王老五
循环中使用条件过滤
可以遍历的同时执行条件过滤:
// for语句 for (e <- 1 to 5) { println(e) } // 只输出偶数 for (e <- 1 to 10 if e % 2 == 0) { println(e) } // 迭代 val books = Array("Scala从入门到精通", "Groovy从入门到精通", "Java从入门到精通", "24小时精通Scala", "24小时精通Java") for(book <- books){ print(book + " || ") } println("\n---------------------------") // 过滤 for(book<-books if book.contains("Scala")){ println(book) }
Scala可以使用一个或多个 if 语句来过滤一些元素:
val numList = Array(1,2,3,4,5,6,7,8,9,10); // for 循环 for( a <- numList if a != 3; if a < 8 ){ println( "a = " + a ); }
输出结果如下:
a = 1 a = 2 a = 4 a = 5 a = 6 a = 7
可以为嵌套循环通过if表达式添加条件:
for (i <- 1 to 3; j <- 1 to 3 if i != j) print ((10 * i + j) + " ") println // if表达式是否添加括号,结果无变化: for (i <- 1 to 3; j <- 1 to 3 if (i != j)) print ((10 * i + j) + " ")
输出结果如下:
12 13 21 23 31 32 12 13 21 23 31 32
【示例】在for条件表达式中使用过滤。
// 打印所有的偶数 for (i <- 1 to 10 if i % 2 == 0) println(i) // 也可写成下面这样 for { i <- 1 to 10 if i % 2 == 0 } println(i) // 多条件 for { i <- 1 to 10 if i > 3 if i < 6 if i % 2 == 0 } println(i)