前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scala专题系列(二):Scala控制结构

Scala专题系列(二):Scala控制结构

作者头像
用户5252199
发布2022-04-18 13:53:36
4140
发布2022-04-18 13:53:36
举报
文章被收录于专栏:大数据技术博文
本片主要内容主要内容包含Scala条件表达式,循环和函数,同时你将学到Scala编程与其它变成语言之间的一种差异。在Java和C++中,表达式和语句是截然不同的,表达式有值而语句只是执行动作。而在Scala中,几乎所有构造出来的语法结构都有值,从而使得程序更加精简,易读

1 :条件表达式

Scala中if/else 语法结构和java,C++一样,不过,在Scala中if/else表达式有值,这个值就是跟在if或者else之后的表达式的值,例如:

if(x >0 ) 1 else -1

那么我们可以这样来写

val s = if(x >0 ) 1 else -1

这个表达式是有值得,最终的值就是1或者-1 ,以上的写法在java中就是

if(x > 0) s = 1 else s = -1

明显的第一种写法会更好一些,因为它可以用来初始化一个val,而在第二种写法中,变量必须是var的

在Java中,有一个三元表达式比如:int i = n > 0 ? 1 : 0

那么这个在scala中就是val s = if(x >0 ) 1 else -1

在Scala中,每个表达式都有一个类型,比如上面你的表达式返回类型是int类型,因为两个分支都是int类型的,但是如果两个分支的类型不同,那么最终返回的就是Scala中的超类Any,Any在Scala中是所有类型的超类

val res = if(n > 0) "result" else 1

比如上面的一条语句,返回的类型就是Any的

2 : 循环

在scala中,while循环和在java与C++中一样

代码语言:javascript
复制
while(n > 0){
    n -= 1
}

在scala中没有与for循环直接对应的结构,如果需要这样的循环我们可以使用while或者使用scala版的for

代码语言:javascript
复制
for( i <- 1 to n ){
    println(i)
}

1 to n 指的是循环1到n个元素索引。

表达式结构:for(i <- 表达式)

让变量i遍历<- 右边的表达式的所有值

在遍历字符串或者数组时,通常需要使用0 到 n-1的区间,这个时候可以用 util方法而不是to,util方法会犯一个并不包含上限的区间

代码语言:javascript
复制
val s = "hello"
var sum = 0
for(i <- i util s.length) sum += s(i)

或者我们并不需要下标

代码语言:javascript
复制
var sum = 0 
for( i <- "hello" ) sum += i 

Scala中并没有提供break或者continue语句来退出循环,那么囚需要break时,该如何做呢

1.使用Boolean类型来控制变量

2:使用嵌套函数-在函数当中return

3:使用Breaks对象中的break方法

代码语言:javascript
复制
breakable{ 
    for( ... ){
    if(...) break 
}
 }

3 : 高级for循环和for推导式

在上面循环中我们只看到了基本的for循环,在scala中for循环比起java和c++功能要丰富很多。下面来看一看for循环的高级特性

可以以变量<-表达式的形式提供多个生成器,用分号将它们隔开

代码语言:javascript
复制
for( i <- 1 to 3 ; j <- 1 to 3 ) println((i + j) + " ")

每个生成器都带一个守卫,以if开头的Boolean表达式

代码语言:javascript
复制
for( i <- 1 to 3; j<-1 to 3  if i != j ) println((i + j) + " ") 

注意:在if之前并没有分号

也可以使用任意多的定义,引入可以在循环中使用的变量

代码语言:javascript
复制
for( i <- 1 to 3 ; from = 4 - i ; j <- from to 3 ) println(i+j)

如果for循环的循环体以yield开始,则该循环会构造出一个集合,每次迭代生成集合中的一个值,比如:

代码语言:javascript
复制
for(i <- 1 to 10) yield i % 3 
  // 生成 Vector(1,2,0,1,2,0,1,2,0,1)

这类循环叫做for推导式

假如你并不需要打印过滤后的集合,你需要编写代码对过滤后的集合进行处理,那么该怎

么办呢?使用 yield 关键字便能在 for 表达式中生成新的集合。比如:

代码语言:javascript
复制
val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund",
"Scottish Terrier", "Great Dane", "Portuguese Water Dog")
val filteredBreeds = for {
breed <- dogBreeds
if breed.contains("Terrier") && !breed.startsWith("Yorkshire")
} yield breed

每次执行 for 表达式时,过滤后的结果将生成 breed 值。随着代码的执行,这些结果

值逐渐积累起来,累计而成的结果值集合被赋给了 filteredBreeds 对象。 for-yield

表达式所生成的集合类型将根据被遍历的集合类型推导而出。在上面的例子中,由

于 filteredBreeds 源 于 dogBreeds 列 表, 而 dogBreeds 类 型 为 List[String], 因 此

filteredBreeds 的类型为 List[String]。

for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用原

括号,当其包含多个表达式时使用大括号。值得注意的是,使用原括号时,

早前版本的 Scala 要求表达式之间必须使用分号。

4 : 懒值(lazy)

当val被声明为lazy时,那么该变量的初始化将被推迟,直到我们首次对它取值。例如

lazy val words = scala.io.Source.fromFile("/usr/local/dic/words").mkString

上面我们定义了一个lazy 的words,如果我们在后面的程序中一直没有调用words,那么这个word就一直不会执行,一直到我们去调用它才会去执行文件的读取操作。

由于表达式执行代价昂贵(例如: 打开一个数据库连接), 因此我们希望能推迟该操作,

直到我们确实需要表达式结果值时才执行它。

• 为了缩短模块的启动时间,可以将当前不需要的某些工作推迟执行。

• 为了确保对象中其他的字段的初始化过程能优先执行,需要将某些字段惰性化

那么惰性赋值与方法调用有那些差别呢?对于方法调用而言,每次调用方法时方法体都会

被执行;而惰性赋值则不然,首次使用该值时,用于初始化的“代码体”才会被执行一

次。这种只能执行一次的计算对于可变字段而言几乎没有任何意义。因此, lazy 关键字并

不能用于修饰 var 变量。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据技术博文 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档