四天掌握Scala(2)
1.5 循环
在 Scala 中,可以使用 for 和 while,但一般推荐使用 for 表达式,因为 for 表达式语法更简洁。
1.5.1 for 表达式
语法格式如下:
for(i <- 表达式/数组/集合) { // 表达式 }
示例: 简单循环,使用 for 表达式打印 1-10 的数字。
步骤:
- 生成 1-10 的数字(提示:使用 to 方法)。
- 使用 for 表达式遍历,打印每个数字。
参考代码1:
scala> val nums = 1.to(10) nums: scala.collection.immutable.Range.Inclusive = Range 1 to 10 scala> for(i <- nums) println(i)
参考代码2:
scala> for(i <- 1 to 10) println(i) 1 2 3 4 5 6 7 8 9 10 scala> for(i <- 1 until 10) println(i) 1 2 3 4 5 6 7 8 9
嵌套循环: 使用 for 表达式,打印以下字符。
*****
*****
*****
参考代码
scala> :paste // Entering paste mode (ctrl-D to finish) for(i <- 1 to 3){ for(i <- 1 to 5){ print("*") } println() } // Exiting paste mode, now interpreting. ***** ***** ***** scala> for(i <- 1 to 3;j <- 1 to 5){print("*");if(j==5) println("*")} ****** ****** ****** scala>
也可以在一个 for 中通过 ;
来定义多层嵌套的 for 循环。
守卫: for 表达式中,可以添加 if 判断语句,这个 if 判断就称之为守卫。我们可以使用守卫让 for 表达式更简洁。
语法
for(i <- 表达式/数组/集合 if 表达式) { // 表达式 }
示例: 使用 for 表达式打印 1-10 之间能够整除 3 的数字。
参考代码:
// 添加守卫,打印能够整除3的数字 scala> for(i <- 1 to 10 if i % 3 == 0) println(i) 3 6 9
for 推导式: 将来可以使用 for 推导式生成一个新的集合(一组数据)。在 for 循环体中,可以使用 yield 表达式构建出一个集合,我们把使用 yield 的 for 表达式称之为推导式。
示例: 生成一个 10、20、30…100 的集合。
参考代码:
// for推导式:for表达式中以yield开始,该for表达式会构建出一个集合 scala> val v = for(i <- 1 to 10) yield i * 10 v: scala.collection.immutable.IndexedSeq[Int] = Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
yield 推导式就是将循环的每一个返回值都收集起来,收集到一个集合中作为 for 循环的返回值。
1.5.2 while 循环
Scala 中 while 循环和 Java 中是一致的。
示例: 打印 1-10 的数字。
参考代码
scala> :paste // Entering paste mode (ctrl-D to finish) var i = 1 while(i <= 10){ println(i) i += 1 } // Exiting paste mode, now interpreting. 1 2 3 4 5 6 7 8 9 10 i: Int = 11 scala>
1.6 break 和 continue
在 Scala 中,类似 Java 和 C++ 的 break/continue 关键字被移除了。如果一定要使用 break/continue,就需要使用 scala.util.control 包的 Break 类的 breakable 和 break 方法。
1.6.1 实现 break
用法
- 导入 Breaks 包
import scala.util.control.Breaks._
。 - 使用 breakable 将 for 表达式包起来。
- for表达式中需要退出循环的地方,添加
break()
方法调用。
示例: 使用 for 表达式打印 1-100 的数字,如果数字到达 50,退出 for 表达式。
参考代码
// 导入scala.util.control包下的Break scala> import scala.util.control.Breaks._ import scala.util.control.Breaks._ scala> breakable{ | for (i <- 1 to 100){ | if(i >= 50) break() | else println(i) | } | }
1.6.2 实现 continue
用法: continue 的实现与 break 类似,但有一点不同:实现 break 是用 breakable{} 将整个 for 表达式包起来,而实现 continue 是用 breakable{} 将 for 表达式的循环体包含起来就可以了。
示例: 打印 1-100 的数字,使用 for 表达式来遍历,如果数字能整除10,不打印。
// 导入scala.util.control包下的Break scala> import scala.util.control.Breaks._ import scala.util.control.Breaks._ scala> for(i <- 1 to 100){ | breakable{ | if(i%10==0)break() | else println(i) | } | }
解答, 为何 break 功能要包住外面,continue 包住 for 循环体呢?因为,在这两种实现中,break 方法都是跳出了 breakable 包含的代码块,向下继续执行。唯一不同的是,如果 breakable 包住 for 循环,那么跳出的时候,就把 for 循环也跳出了,就向下继续执行了,就实现了类似 java 中 break 的功能。如果 breakable 包住 for 循环的循环体的话,那么跳出的时候,还在 for 循环内,只是当前这一次的循环体执行完成了,所以继续执行就是继续执行下一次的 for 循环。所以,包住的地方不同,实现的功能不同,但是对于 breakable 和 break 来说,他们的功能从未改变。
1.7 方法
一个类可以有自己的方法,Scala 中的方法和 Java 方法类似。但 Scala 与 Java 定义方法的语法是不一样的。
1.7.1 定义方法
语法
def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = { // 方法体:一系列的代码 }
- 参数列表的参数类型不能省略(因为之前定义变量的时候可以省略,这里不要混淆了,因为变量给了初始值,可以根据初始值推断类型)。
- 返回值类型可以省略,由 Scala 编译器自动推断。
- 返回值可以不写 return,默认就是 {}块表达式的值。
示例:
- 定义一个方法,实现两个整形数值相加,返回相加后的结果。
- 调用该方法。
参考代码
scala> def add(a:Int, b:Int) = a + b add: (a: Int, b: Int)Int scala> add(5,6) res4: Int = 11
1.7.2 返回值类型推断
Scala 定义方法可以省略返回值,由 Scala 自动推断返回值类型。这样方法定义后更加简洁。定义递归方法,不能省略返回值类型。因为,递归调用是一层一层向内走,当前那一层无法推断返回类型,会导致一系列问题。
示例: 定义递归方法(求阶乘),比如求 10 的阶乘,10 * 9 * 8 * 7 * 6 * ... * 1
参考代码
1.8 方法参数
Scala 中的方法参数,使用比较灵活。它支持以下几种类型的参数:默认参数、带名参数、变长参数。
1.8.1 默认参数
在定义方法时可以给参数定义一个默认值。
示例:
- 定义一个计算两个值相加的方法,这两个值默认为 0。
- 调用该方法,不传任何参数。
参考代码
// x,y带有默认值为0 scala> def add(x:Int = 0, y:Int = 0) = x + y add: (x: Int, y: Int)Int scala> add() res5: Int = 0
1.8.2 带名参数
在调用方法时,可以指定参数的名称来进行调用。
示例:
- 定义一个计算两个值相加的方法,这两个值默认为 0。
- 调用该方法,只设置第一个参数的值。
参考代码:
scala> def add(x:Int = 0, y:Int = 0) = x + y add: (x: Int, y: Int)Int scala> add(1) res6: Int = 1
1.8.3 变长参数
如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。语法格式如下:
def 方法名(参数名:参数类型*):返回值类型 = { 方法体 }
在参数类型后面加一个 *
号,表示参数可以是0个或者多个。
示例:
- 定义一个计算若干个值相加的方法。
- 调用方法,传入以下数据:1,2,3,4,5。
参考代码:
scala> def add(num:Int*) = num.sum add: (num: Int*)Int scala> add(1,2,3,4,5) res7: Int = 15
其他:Scala 允许指定最后一个参数是可变长度的,或者唯一一个参数。变长参数,在函数体内本质上是一个 Array 实例,也就是除了例子里面的 sum 外,我们也可以用 for 循环迭代它,如:
scala> def add(x:Int*): Int={ | var result=0 | for(i <- x) result += i | result | } add: (x: Int*)Int scala> add(1,2,3) res8: Int = 6
虽然它本质上是一个 Array,但是你不可以将 Array 对象传递给它,如果要传递需要传递如 array:_* 表明将每个元素传递给它,而不是整个数组对象。如:
add(ar:_*)