定义主函数
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
//交互式命令行调用
HelloWorld.main(null)
Scala代码作为脚本语言
./hello.sh
#!/bin/sh
exec scala "$0" "$@"
!#
object HelloWorld extends App {
println("Hello, world!")
}
HelloWorld.main(null)
Scala解释器命令
可以输入任意的Scala表达式
在命令行中需要分多行输入,Scala解释器在新行前面显示|
//退出
quit
//多行
val msg3=
| "Hello world 3rd time"
定义变量
Scala的“type inference”特点 ;类型推导-自动推测类型
val 类似于Java中的final 变量 不可以重新复制
var 可以任意重新赋值
//默认会自动推测类型
val msg="Hello,World"
//也可以定义类型
val msg1:String ="Hello again,world"
var msg2="Hello,World2"
msg2="haha"
定义函数
函数在Scala语言中的地位和类是同等第一位的
每个Scala表达式都有返回结果
函数的最后一个表达式的值就可以作为函数的结果作为返回值
def max(x:Int,y:Int) : Int ={
if (x >y) x
else
y
}
max(6,7)
def max2(x:Int,y:Int) : Int ={if (x >y) x else y}
max2(9,7)
//无返回值 显示Unit相当于void
def greet() = println("hello,world")
while循环
scala不支持i++使用i+=1代替
var args="asdasdasd"
var i=0
while (i < args.length) {
println (args(i))
i+=1
}
#Scala访问数组的语法是使用()
foreach 和 for 来实现迭代
采用“函数式”风格
args.foreach(arg => println(arg))
//简写
args.foreach( println)
//for
for (arg <-args)
println(arg)
初始化数组Array
Array可以修改内容
val greetStrings = new Array[String](3)
greetStrings(0)= "Hello"
greetStrings(1)= ","
greetStrings(2)= "world!\n"
for(i <- 0 to 2)
print(greetStrings(i))
//简化
val greetStrings =Array("Hello",",","World\n")
Lists
Scala的Lists对象是不可修改的
List只能包含同类型的数据
val oneTwo = List(1,2)
val threeFour = List(3,4)
val oneTwoThreeFour=oneTwo ::: threeFour
println (oneTwo + " and " + threeFour + " were not mutated.")
println ("Thus, " + oneTwoThreeFour + " is a new list")
Scala 的List类 head、last、length、reverse、tail等
head、last、length、reverse、tail
oneTwoThreeFour.head list第一个元素
oneTwoThreeFour.last list最后一个元素
reverse反转length长度
oneTwoThreeFour.tail 除去第一个的其他元素
:::连接两个列表
::添加元素
//向List中添加一个元素
val oneTowThree = 1 :: 2 ::3 :: Nil
println(oneTowThree)
元组(Tuples)
Tuples可以包含不同类型的数据
返回多个结果时非常有用
对应到数学的矢量
//可以使用._索引 来访问员组的元素,元组的索引从1开始
val pair=(99,"Luftballons")
println(pair._1)
println(pair._2)
Sets和Maps
set不可修改
map可修改
var jetSet = Set ("Boeing","Airbus")
//添加元素
jetSet +="Lear"
//判断是否存在
println(jetSet.contains("Cessna"))
val romanNumeral = Map ( 1 -> "I" , 2 -> "II",
3 -> "III", 4 -> "IV", 5 -> "V")
println (romanNumeral(4))
函数编程风格
能不用vars,尽量不用vars,能不用mutable变量,尽量不用mutable变量,能避免函数的副作用,尽量不产生副作用。
//java风格不推荐
def printArgs ( args: Array[String]) : Unit ={
var i=0
while (i < args.length) {
println (args(i))
i+=1
}
}
//去var变量
def printArgs ( args: Array[String]) : Unit ={
for( arg <- args)
println(arg)
}
//更简化
def printArgs ( args: Array[String]) : Unit ={
args.foreach(println)
}
读取文件
import scala.io.Source
def readfile( args: String) : Unit ={
if (args.length >0 ){
for( line <- Source.fromFile(args).getLines())
println(line.length + " " + line)
}
else
Console.err.println("Please enter filename")
}
readfile("/Users/yuyin/Downloads/myfile/note/test.txt")
枚举当前目录下所有文件
val filesHere = (new java.io.File(".")).listFiles
for( file <-filesHere)
println(file)
类和对象的定义
以class 开始
缺省修饰符为public
Scala的方法的参数都是val类型,在函数体内不可以修改参数的值
class ChecksumAccumulator{
private var sum=0
def add(b:Byte) :Unit = sum +=b
def checksum() : Int = ~ (sum & 0xFF) +1
}
import scala.collection.mutable.Map
class ChecksumAccumulator{
private var sum=0
def add(b:Byte) :Unit = sum +=b
def checksum() : Int = ~ (sum & 0xFF) +1
}
object ChecksumAccumulator {
private val cache = Map [String, Int] ()
def calculate(s:String) : Int =
if(cache.contains(s))
cache(s)
else {
val acc=new ChecksumAccumulator
for( c <- s)
acc.add(c.toByte)
val cs=acc.checksum()
cache += ( s -> cs)
cs
}
}
println ( ChecksumAccumulator.calculate("Welcome to Scala Chinese community"))
控制语句if
//java风格
var filename="default.txt"
if(!args.isEmpty)
filename =args(0)
//scala风格
val filename=
if(!args.isEmpty) args(0)
else "default.txt"
for生成新集合
//生成Array[File]
def scalaFiles =
for {
file if file.getName.endsWith(".scala")
} yield file
用 try 表达式处理异常
val half =
if (n % 2 == 0)
n/2
else
throw new RuntimeException("n must be even")
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => //handle missing file
case ex: IOException => //handle other I/O error
}
finally
通常情况下,finally块用来做些清理工作,而不应该产生结果
import java.io.FileReader
val file = new FileReader("input.txt")
try {
//use the file
} finally {
file.close()
}
Match 表达式
Scala的缺省匹配为“_”
val firstArg = if (args.length >0 ) args(0) else ""
firstArg match {
case "salt" => println("pepper")
case "chips" => println("salsa")
case "eggs" => println("bacon")
case _ => println("huh?")
}
使用true判断代替break与continue
var i=0
var foundIt=false
while (i < args.length && !foundIt) {
if (!args(i).startsWith("-")) {
if(args(i).endsWith(".scala"))
foundIt=true
}
i=i+1
}
递归函数重新实现上面代码实现的查询功能:
def searchFrom(i:Int) : Int =
if( i >= args.length) -1
else if (args(i).startsWith("-")) searchFrom (i+1)
else if (args(i).endsWith(".scala")) i
else searchFrom(i+1)
val i = searchFrom(0)
filter方法用来过滤集合中的元素
val someNumbers = List ( -11, -10, - 5, 0, 5, 10)
someNumbers.filter( x => x >0)
//Scala允许使用“占位符”下划线“_”来替代一个或多个参数,只要这个参数值函数定义中只出现一次,Scala编译器可以推断出参数
someNumbers.filter(_ >0)
//print _ 来代替 println (_)
someNumbers.foreach( x => println (x))
someNumbers.foreach(println _)
部分应用函数
一个部分应用的函数指的是你在调用函数时,不指定函数所需的所有参数
//固定sum的第一和第三个参数
def sum = (_:Int) + (_ :Int) + (_ :Int)
val b = sum ( 1 , _ :Int, 3)
b(2)
闭包
引用到函数外面定义的变量
var more =1
val addMore = (x:Int) => x + more
addMore (100)
more=11
addMore (100)
可变参数
“*”来指明该参数为重复参数 变长参数
//String * 类型实际为 Array[String]
def echo (args: String *) = for (arg <- args) println(arg)
echo("x")
echo("x","ss")
_* 在传递参数时,逐个传入数组的每个元素
val arr= Array("What's","up","doc?")
echo (arr: _*)
柯里化函数(Currying)
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
//非柯里化
def plainOldSum(x:Int,y:Int) = x + y
plainOldSum(1,2)
//柯里化
def curriedSum(x:Int)(y:Int) = x + y
curriedSum (1)(2)
Scala的类层次关系
所有的类都继承自Any,因此Scala中的对象都可以使用==、!=或equals来比较,使用##或hashCode给出hash值,使用 toString 转为字符串。
AnyVal是Scala里每个内建值类型的父类。有九个这样的值类型:Byte,Short,Char,Int,Long,Float,Double,Boolean和Unit
方法min、max、until、to和abs都定义在类scala.runtime.RichInt里,并且有一个从类Int到RichInt的隐式转换。
AnyRef是Scala里所有引用类的基类,似java.lang.Object
Trait
集合了Interface和抽象类的优点,同时又没有破坏单一继承的原则
可以使用extends或with来混合一个trait
trait Philosophical{
def philosophize() {
println("I consume memeory, therefor I am!")
}
}
class Frog extends Philosophical{
override def toString="gree"
}
val frog = new Frog
frog.philosophize