目录
摘要
if 与表达式与 else,for,until,for 与字符串,for 与对象列表,break 与 continue,生成器,守卫,循环变量,yield,map,FlatMap,filter,stream,iterator
流程控制
条件表达式
if/else
结构与 Java 类型,不过由于 Scala 面向表达式,所以可以直接将表达式赋给一个变量。
val s = if (x > 0) 1 else -1
这种方式可以给常量赋值,有点类似 Java 中得三元操作符,此时 s 的类型为 Int
如果下面这种混合型的,s 的类型就为 Any
val s = if (x > 0) "a" else 65
因为 Scala 中表达式都必须有值,所以如果没有 else
的话,需要引入 Unit 类,写作 ()
if (x > 0) 1 else ()
循环
while 和 do-while
Scala 中的 while
和 do-while
类似 Java
for
基本使用
for (i <- 1 to n)
此表达式表示让变量 i
遍历 <-
右边的表达式的所有值 ( “1” 到 “n” )
变量 i
不需要事先定义,循环变量的作用域会一直持续直到循环结束。
for (i <- 1 until n)
until
until
表示不包含上区间
for (i <- 1 until 5)
print(i) //1234
println()
用于字符串上
for (ch <- "Hello")
sum += ch
用于对象列表
for 也可以用在对象列表上
class Person(val name: String, val age: Int) {
}
val persons = List(new Person(name = "Jane", age = 18), new Person(name = "Peter", age = 20),
new Person(name = "Anna", age = 15), new Person(name = "Andy", age = 22))
val ages = for (p <- persons if p.age > 20) yield p.age
//以上代码实际会被翻译成如下代码
val newAges = persons filter (p => p.age > 20) map (p => p.age)
println(ages) //List(22)
println(newAges) //List(22)
break 和 continue
Scala 没有提供 break
和 continue
来退出循环,需要自己定义 boolean 变量来控制或者从函数中 return。
高级 for 循环
生成器
生成器的格式是 变量 <- 表达式
在 for
循环中可以同时使用多个生成器,每个生成器之间用分号隔开,或者换行分隔。
for (i <- 1 to 3; j <- 3 to 5) {
print(i, j) //(1,3)(1,4)(1,5)(2,3)(2,4)(2,5)(3,3)(3,4)(3,5)
}
守卫
每个生成器都可以带一个守卫,守卫是以 if 开头的布尔表达式
for (i <- 1 to 3; j <- 3 to 5 if i == j) {
print(i, j) //(3,3)
}
循环变量
for 循环中也可以自由定义任何变量,不用以 val 和 var开头
for(i <- 1 to 3; from = 4 - i; j <- from to 3)
yield
如果 for
循环的循环体以 yield
开头,则该循环会生成一个集合,每次迭代生成集合中的一个值。这种 for
循环称为 “for 推导式”。
var result = for (i <- 1 to 10) yield {
i % 3
}
println(result) //Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)
“for 推导式” 生成的集合与它的第一个生成器是类型兼容的。
隐式 for 循环
概念
由于 for
循环是非常常用的方法,所以 Scala 提供了很多简便方法
Map
Map
用于对列表中的每一个元素进行遍历
val persons = List(new Person(name = "Jane", age = 18), new Person(name = "Peter", age = 20),
new Person(name = "Anna", age = 15), new Person(name = "Andy", age = 22))
persons.map(p => p.age) //List(18, 20, 15, 22)
FlatMap
FlatMap
用于对列表中的每一个元素应用函数并以列表形式返回结果。
val persons = List(new Person(name = "Jane", age = 18), new Person(name = "Peter", age = 20),
new Person(name = "Anna", age = 15), new Person(name = "Andy", age = 22))
persons.flatMap(p => List(p.age)).foreach(p => println("flatMap", p)) //(flatMap,18)(flatMap,20)(flatMap,15)(flatMap,22)
Filter
Filter
用于对按照布尔值对列表中元素进行过滤。
val persons = List(new Person(name = "Jane", age = 18), new Person(name = "Peter", age = 20),
new Person(name = "Anna", age = 15), new Person(name = "Andy", age = 22))
persons.filter(p => {
if (p.age > 20) true else false
}).foreach(p => println("filter", p.age)) //(filter,22)
Stream
概念
- 由于实际编程中像
[start .. end-1]
这种形式的遍历非常常见,所以 Scala 提供了Stream
来进行简便操作。 Stream
对象是不可变对象,由单个元素的头部及其余部分组成的尾部构成
使用方法
指定范围
var r: Stream[Int] = Stream.range(1, 5)
println(r, r.getClass, r.head, r.tail) //(Stream(1, 2, ?),class scala.collection.immutable.Stream$Cons,1,Stream(2, ?))
r.foreach(i => println(i)) //1,2,3,4
以上方法内部实现类似下面的代码
def range(start: Int, end: Int): Stream[Int] = {
if (start >= end) Stream.Empty
else Stream.cons(start, range(start + 1, end))
}
r = range(1, 5)
println(r, r.getClass, r.head, r.tail) //(Stream(1, 2, ?),class scala.collection.immutable.Stream$Cons,1,Stream(2, ?))
r.foreach(i => println(i)) //1,2,3,4
连接元素
Stream.cons(ele, stream)
可以用于追加新元素到头部并返回新生产的 Stream
对象,该方法实际就类似 List
的 a::b
。
var nr = Stream.cons(30, Stream.range(1, 5))
println(nr, nr.getClass, nr.head, nr.tail) //(Stream(30, 1, ?),class scala.collection.immutable.Stream$Cons,30,Stream(1, ?))
nr.foreach(i => println(i)) //30,1,2,3,4
Iterator
概念
Iterator
和 Stream
一样,也是用于对数据进行遍历
创建 Iterator
val it: Iterator[Int] = Iterator.range(1, 5)
while (it.hasNext) {
val v = it.next()
println("it", v) //1,2,3,4
}
Map
map
用于遍历每个元素并对每个元素应用方法,返回函数的执行结果
val it2 = Iterator.range(1, 5).map(i => i + 5)
while (it2.hasNext) {
val v = it2.next()
println("it2", v) //6,7,8,9
}
FlatMap
FlatMap
类似 map
,但返回的是 Iterator
val it3 = Iterator.range(1, 5).flatMap(i => Iterator.range(i, i + 2))
while (it3.hasNext) {
val v = it3.next()
println("it3", v) //1,2|2,3|3,4|4,5
}
for each
Iterator.range(1, 5).foreach(i => println("it4", i)) //1,2,3,4
Filter
Filter
根据返回的布尔值过滤对应值。
val it5 = Iterator.range(1, 5).filter(i => i % 2 == 0)
while (it5.hasNext) {
val v = it5.next()
println("it5", v) //2,4
}
Zip
Zip
用于连接两个 Iterator
的值,返回匹配后的新的 Iterator
。
var it6 = Iterator.range(1, 5).zip(Iterator.range(10, 20))
while (it6.hasNext) {
val v = it6.next()
println("it6", v) //(1,10),(2,11),(3,12),(4,13)
}
it6 = Iterator.range(1, 5).zip(Iterator.range(10, 12))
while (it6.hasNext) {
val v = it6.next()
println("it6", v) //(1,10),(2,11)
}