随机数
import java.util.Random
val rand = new Random()
val x = rand.nextInt()
scala 数学包
import scala.math._
sqrt(2)
pow(2,4)
min(2,4)
没有参数且不改变当前对象的方法不带圆括号
"hello".distinct
使用伴生对象的apply方法来构建对象(常用),不需要new关键字
BigInt("123456")
条件表达式有值
val s = if(x>0) 1 else -1
如果语句很长要换行尽量用“操作符”作为第一行的结尾,
val s = s0 + (v1-v0) +
0.5*(v3-v2)
块中最后一个表达式的值就是块的值
{ exp1
exp2
}
循环
for( i <- 1 to 10)
for( i <- 1 until 10)
没有break,需通过布尔表达式或函数返回
函数
方法对对象进行操作,函数不是
def abs(x: Double) = if(x >= 0) x else -x
递归函数必须指出返回值类型
def fac(x:Int):Int = if( x<=0 ) 1 else x*fac(x-1)
过程
有花括号,但是没有前面的等号,其返回值是Unit类型,这样的函数叫过程
异常
try{}catch{}finally{}
数组
定长数组
val nums = new Array[Int](10)
val s =new Array[String](10)
val s2 = Array("hi","hello")
s(0) = "apple" //通过()来访问元素
变长数组
import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()//空的数组缓冲
b += 1
b += (5,6)
b ++= Array(2,3,4)
val a = b.toArray//ArrayBuffer转Array
c = a.toBuffer//Array转ArrayBuffer
遍历数组
0 until a.length
0 until (a.length,2)//每两个取一个
for(elem <- a){yield elem*2}
常用操作
import scala.util.Sorting.quickSort
a.filter(_%2==0).map(2*_)
a.sum
a.max
a.min
a.sortWith(_<_)
quickSort(a)//直接改变原数组
映射和元组
Map
import scala.collection.mutable
//不可变map
val scores = Map("Alice"->3,"Bob"->4)
//或者scores = Map(("A",1),("B",2))
val tmp = scores("Alice")//获取值
//判断key是否存在
scores.contains("Alice")//true
scores.contains("d")//false
//获取value更普遍的用法
val tmp = scores.getOrElse("Alice",0)
//可变map
val scores = mutable.Map("Alice"->3,"Bob"->4)
scores("Cindy") = 5//新增键值
scores += (("Lemon",3),("Honey",8))//添加多个
scores += ("oo"->3,"mm"->8)//添加多个
scores -= "Alice"//删除key
//新建空的map
val scores = new mutable.HashMap[String,Int]
//遍历Map
for((k,v)<-scores) println(v)
for(v<-scores.values) println(v)//values方法返回一个Iterable
//调换k,v
for((k,v)<-scores) yield(v,k)
//已排序映射,按key升序排
val scores = scala.collection.immutable.SortedMap("Alice"->10,"Bob"->2)
//按插入顺序访问的映射
val scores = scala.collection.mutable.LinkedHashMap("Jan"->1,"Feb"->2,"Mar"->3)
元组
val t = (1,'A',"Apple")
//访问元素
val tmp = t._2//元组的下标从1开始
//模式匹配
val (a,b,c) = t
zip操作
val a = Array('a','b','c')
val b = Array(1,2,3)
val c = a.zip(b)//c: Array[(Char, Int)] = Array((a,1), (b,2), (c,3))
//toMap方法将对偶集合转为映射
val d = c.toMap//d:scala.collection.immutable.Map[Int,Char] = Map(1 -> a, 2 -> b, 3 -> c)
类
pulic是scala的默认访问级别
scala源文件可以包含很多个类,这些类都具有公共可见性
调用改值器(改变对象状态)方法,加(),如myCounter.increment()
调用取值器(不改变对象状态)方法,不加(),如myCounter.current
getter和setter方法
scala为每个字段都提供了getter和setter方法
scala中getter和setter分别叫做age,age_
class Person{
var age = 0
}
var fred = new Person
println(fred.age)//getter
fred.age = 20//setter
如果字段是私有的,则getter和setter方法也是私有的
如果字段值val,那么只有getter方法被生成,这是一个只读属性
自定义getter和setter方法
class Person{
private var privateAge=0
def age = privateAge
def age_ = (newValue:Int){
if(newValue>privateAge)
privateAge = newValue
}
var foo: scala自动生成getter和setter方法
val foo:scala自动生成getter方法
可以自己定义getter和setter方法
@BeanProperty
import scala.beans.BeanProperty
class Person{
@BeanProperty var name:String = _
}
val p = new Person
p.setName("hi")
println(p.getName)
使用BeanProperty属性后,会为字段自动生成以下四种方法:
name
name_
getName
setName
辅助构造器
辅助构造器名称为this
每个辅助构造器都必须以一个先前定义的辅助构造器或主构造器的调用开始
class Person{
@BeanProperty var name:String = _
var age:Int = 0
def this(name:String){
this()//主构造器
this.name = name
}
def this(name:String,age:Int){
this(name)//前一个辅助构造器
this.age = age
}
}
val p = new Person//主构造器
val p1 = new Person("le")//第一个辅助构造器
val p2 = new Person("le",10)//第二个辅助构造器
主构造器
没有显示定义主构造器的自动拥有一个无参数的主构造器
主构造器的参数直接放在类名之后
class MyPerson(val name:String,val age:Int){
}
object Demo{
def main(args:Array[String]):Unit={
val p = new MyPerson("hi",2)
println(p.name)
println(p.age)
}
}
对象-object
单例对象
定义了某个类的单个实例
对象的构造器在对象第一次被使用时调用
对象的构造器不能有参数
object Accounts{
private var lastNumber = 0
def newUniqueNumber() = {lastNumber+=1;lastNumber}
}
object Demo{
def main(args:Array[String]):Unit={
println(Accounts.newUniqueNumber)//Accounts的构造器在Accounts.newUniqueNumber首次调用时执行
}
}
伴生对象
在java中既有实例又有静态方法的类在scala中可以通过类和与类同名的伴生对象来达到同样目的。
类和伴生对象必须在同一个源文件中
类和伴生对象可以相互访问其私有属性
class Account{
val id = Account.newUniqueNumber()
private var balance = 0.0
def deposit(amount:Double){balance+=amount}
}
object Account{
private var lastNumber = 0
def newUniqueNumber() = {lastNumber+=1;lastNumber}
}
apply方法
调用形式:object(参数1,参数2,...)
例如:Array(1,2,4)
这样就可以省去new关键字
apply方法返回的是伴生类的对象
class Account private(val id:Int,initialBalance:Double){
private var balance = initialBalance
def deposit(amount:Double){balance+=amount}
}
object Account{
private var lastNumber = 1
def newUniqueNumber() = {lastNumber+=1;lastNumber}
def apply(initialBalance:Double)={
new Account(newUniqueNumber(),initialBalance)
}
}
object Demo{
def main(args:Array[String]):Unit={
val acct = Account(1000.0)//apply方法
}
}
scala project必须从一个对象的main方法开始
object Demo{
def main(args:Array[String]):Unit={//参数args:Array[String],返回值Unit
...
}
}
包和引入
串联式包语句
package com.horstman.impatient
在这里com,com.horstman
是不可见的
文件顶部标记法
package com.horstman.impatient
package people
class Person
...
相当于
package com.horstman.impatient{
package people{
class Person
...
}
}
包对象
包里面可以包含class,object,trait,但是不能包含函数或者变量的定义。包对象就可以解决这个问题。
包对象里面可以定义一些工具函数和常量
包对象在父包中定义,与子包的名字相同
包对象被编译为带有静态方法和字段的JVM类
package com.horstman.impatient
package object people{
val defaultName = "hello"
}
package people{
class Person{
var name = defaultName
}
}
引入
import scala.collection.mutable._
“_”是通配符,相当于java中的”*”,表示引入包/类/对象的所有成员
选取器
import java.awt.{Color,Font}
import java.util.{HashMap => JavaHashMap}//重命名
import java.util.{HashMap -> _, _}//隐藏HashMap
继承
扩展类 extends
class Employee extends Person{
var salary = 0.0
...
}
重写 override
重写一个非抽象方法必须用override关键字
class Employee extends Person{
override def toString = ...
}
调用超类的方法用super关键字
override def toString = super.toString ...
类型检查及转换
isInstanceOf
asInstanceOf
if(p.isInstanceOf[Employee]{
val s = p.asInstanceOf[Employee]
}
想确定p指向的是Employee对象而且不是其子类
if(p.getClass==classof[Employee]
更推荐模式匹配的方法
p match{
case s: Employee=>...//
case _: ...//不是Employee
}