22.13. main方法
Scala的main方法(包括所有类似java的static方法)必须定义在一个object内:
object Test1 {
def main(args: Array[String]) {
println("hello world")
}
}
2.13.1. Application
不带命令行参数的简化main方法:
object app1 extends Application {
println("hello world")
}
2.14. package, import
2.14.1. import
Scala的import可以只在局部作用域内生效;
可以格式 “import javax.swing.{JFrame=>jf}”来声明类型的别名。
jf.show()
l import javax.swing._
l import java.util.{List, Map}
l import java.util._, java.io._
Scala 缺省导入如下包:
l java.lang.*
l scala.*
l scala.Predef
由于Scala的package可以是相对路径下定义,有可能命名冲突,可以用:
import _root_.java.lang.Long
2.14.2. package
package com.wr3 {
// import java.nio._ // "*" 是scala的正常函数名,所以用_
class c1 {
def m1() { println("c1.m1()") }
}
object o1 {
def main(args: Array[String]) {
println("o1.main()")
new c1().m1()
}
}
}
编译:
fsc package.scala
运行:
java com.wr3.o1 // 方式1
scala com.wr3.o1 // 方式2
2.15. if..else
没有java的:
b = (x>y) ? 100 : -1
就用:
if (x>y) 100 else -1
2.16. 循环操作
map | m->m |
flatMap | m->n |
indices | m->m |
foreach | m->Unit |
for (... if ...) yield | m->n |
collect { case ... if ... => ... } | m->n |
filter, filterNot | m->n |
take | m->n |
takeWhile | m->n |
forall | m->1 (true|false) |
reduceLeft, foldLeft | m->1 |
scanLeft | m->m+1 |
exists | m->1 (true|false) |
find | m->1 (或者None) |
count | m->1 |
span, partition | m->2 |
2.16.1. for
循环中的变量不用定义,如:
for(i<-1 to 10; j=i*i) println(j)
for (s <- ss) foo(s)
for (i <- 0 to n) foo(i) // 包含n,即Range(0,1,2,...,n,n+1)
for (i <- 0 until n) foo(i) // 不包含n,即Range(0,1,2,3,...,n)
例如:
for (n<-List(1,2,3,4) if n%2==1) yield n*n // List(1, 9)
等价于不用for的写法:
List(1,2,3,4).filter(_%2==1).map(n => n*n)
for (n<-Array(1,2,3,4) if n%2==1) yield n*n // Array(1, 9)
注意:如果if后面不止一条语句,要用{..}包裹。
var s = 0; for (i <- 0 until 100) { s += i } // s = 4950
for条件语句即可用(),也可用{}
如果条件是多行,不能用(),要用{}
for(i<-0 to 5; j<-0 to 2) yield i+j
// Vector(0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5 , 6, 5, 6, 7)
for{i<-0 to 5
j<-0 to 2} yield i+j
例子1:
// 边长21以内所有符合勾股弦的三角形:
def triangle(n: Int) = for { x <- 1 to 21 y <- x to 21 z <- y to 21 if x * x + y * y == z * z } yield (x, y, z)
结果:
// Vector((3,4,5), (5,12,13), (6,8,10), (8,15,17), (9,12,15), (12,16,20))
2.16.1. for .. yield
把每次循环的结果“移”进一个集合(类型和循环内的一致)
for {子句} yield {循环体}
正确:
for (e<-List(1,2,3)) yield (e*e) // List(1,4,9)
for {e<-List(1,2,3)} yield { e*e } // List(1,4,9)
for {e<-List(1,2,3)} yield e*e // List(1,4,9)
错误:
for (e<-List(1,2,3)) { yield e*e } // 语法错误,yield不能在任何括号内
yield 关键字的简短总结:
- 针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
- 当循环结束后, 会返回所有 yield 的值组成的集合.
- 返回集合的类型与被遍历的集合类型是一致的.
2.16.2. foreach
List(1,2,3).foreach(println)
1
2
3
也可以写成:
(1 to 3).foreach(println)
或者
(1 until 4) foreach println
或者
Range(1,3) foreach println
注意:
l to包含,until不包含(最后的数)
l 都可以写步长,如:
1 to (11,2) // 1,3,5,7,9,11 步长为2
== 1 to 11 by 2
1 until (11,2) // 1,3,5,7,9
== 1 until 11 by 2
val r = (1 to 10 by 4) // (1,5,9), r.start=r.first=1; r.end=10, r.last=9
l 也可以是BigInt
(1:BigInt) to 3
forall看的例子不是很能理解清楚,留待补充。
2.16.4. reduceLeft
reduceLeft 方法首先应用于前两个元素,然后再应用于第一次应用的结果和接下去的一个元素,等等,直至整个列表。例如
计算阶乘:
def fac(n: Int) = 1 to n reduceLeft(_*_)
fac(5) // 5*4*3*2 = 120
相当于:
((((1*2)*3)*4)*5)
计算sum:
List(2,4,6).reduceLeft(_+_) // 12
相当于:
((2+4)+6)
取max:
List(1,4,9,6,7).reduceLeft( (x,y)=> if (x>y) x else y ) // 9
或者简化为:
List(1,4,9,6,7).reduceLeft(_ max _) // 9
相当于:
((((1 max 4) max 9) max 6) max 7)
2.16.9. break、continue
Scala中没有break和continue语法!需要break得加辅助boolean变量,或者用库(continue没有).
https://blog.csdn.net/zhangjianbo1989/article/category/2533993