Scala学习笔记:
1.1 scala的基础语法
声明与定义(赋值):声明变量时可以指定类型,不指定也可以自动识别数值类型
ØVal常量val x = 10val x:Int=10
ØVar变量
Ø可以一次声明多个变量val x1,x2,x3 =10
Ødef声明函数
Øscala的注释:跟java中的相同,//行注释/**/块注释
1.2数值类型
支持4种数据类型:
Ø整行值:Int、Long,Short,Double
Ø浮点型值:FloatDouble
Ø布尔型值:Boolean(truefalse)
Ø字符型值:CharString// char使用‘’String使用“”进行区分(自动识别)
操作符运算:
Ø数学操作符:+ - * / %
Ø比较操作符:> < >= <=产生布尔值
Ø逻辑操作符:&&||产生布尔值
Ø对等操作符:==!=布尔值
Ø位操作符:& | ^ ~
通用规范:
ØScala基于行的语言,分号和换行均可作为语句的结束
Ø多行做为一个整体,使用{}创建符合表达式,大括号之间的语句不作为语句的结束
Ø尽量不要使用保留字
1.3 scala语言入门
1.3.1结构
主要是学会scala程序块中的结构控制语句
(1)判断(if表达式)
def max(x:Int,y:Int) = if(x>y) x else y//if可以作为返回值进行复制
(2)循环(while..do)
val x=10
while(x>0){
if(x%2==0){
println(x)
}
x-=1
}
(3)枚举(for枚举):枚举对象可以为范围,也可以为数组、字符串等
使用指针指向:
for (x <- 1 to 10) println(x)
//还可以在for枚举的条件中添加if判断,
for( x<-1 to 10;if(x%2==0)) println(x)或for(x <- 1 to 10 if x%2==0) println(x)
//多层嵌套枚举;同样也可以添加筛选条件
for(x <- 1 to 10;y <- 1 to 5 )
println(x*y)
// for枚举后的表达式可以作为结果返回:关键字yield
val v = for( x <- 1 to 10) yield x //v = Vector[1,2,3 ….,10]
(4)匹配(match表达式):类似于java中的case when
a match{
case
e1 => E1
case e2 => E2
}
(5)异常处理(throw、try)类似于java
(6)输出(print、println)
类似于java的console输出
(7)输入(readLine、readInt)
用于从控制台,接收输入的数值
Var name = readLine(“please input your
name:”)
Scala程序中,最后一行返回的数值,就是return的结果,所以无需单独使用return语句
1.3.2数组
(1)数组的声明;
Var arr = new Array[T](10)//初始化声明数组的长度,及类型
Var arr = Array(123,234)//自动识别创建的数组的
(2)数据的使用:
数组的下标是从0开始的,arr.length-1结束;超过会显示数组下标越界
获取数据的值:arr(下标)eg:arr(0)
(3)可变数组
引入ArrayBuffer类:import scala.collection.mutable.ArrayBuffer
Ø初始化ArrayBuffer
Valarr = ArrayBuffer[T]()
Ø增加元素
arr+=(1,2,3,4)
Ø增加一个数组
arr ++= Array(200,300)
Ø截掉最后的2个元素
arr.trimEnd(2)
Ø在第2个位置,插入元素元素100(可以插入多个元素,下标从0开始,插入位置不要超过数组的最长下标)
arr.insert(2,100,200)
Ø移除下标为3位置的元素
arr.remove(3)
Ø移除下标为2位置开始的,3个元素
arr.remove(2,3)
Ø可变数组转换成不变数组
var arr1 = arr.toArray
Ø将不可变数组转换成可变数组
Var arr2 = arr.toBuffer
Ø倒序遍历
for(x <- arr2.reverse)
println(x)
Ø数组排序:引入import scala.util.Sorting
Var arr1 = Sorting.quickSort(arr)
//升序排序
Ø拼接数组为字符串,指定分割符
arr.mkString(“,”)// 1,2,3,4
1.3.3映射
类似于java中的map集合
(1)映射的声明:
Ø两种方式;
Val map = Map(a1 ->
b1,a2->b2,a3->b3)
或者:val map =
Map((a1,b1),(a2,b2),(a3,b3))
(2)映射的使用;
Ø获取对应键的值
Var value = map(a1)或者var value =
map.get(a1)
Ø使用contains方法检查映射中是否含有某个key,返回boolean
Var v = map.contains(a1)
Ø组合调用,getOrElse方法,
Var v = map.getOrElse(a1,0)#如果有key则返回value值,否则返回0
Ø更新或新增map值
map += (a4 -> b4)
Ø删除键值对应
map -= a4
Ø映射的枚举
for((x,y) <- map) println("key:"+x+"value:"+y)
Ø分别获取键、值的集合
Var key = map.keySet
Var value = map.values
1.3.4元组
(1)元组是不同类型值的集合,映射是二元的元组
var g = (1,1.2,'a',"mapeng")
g: (Int, Double, Char, String) = (1,1.2,a,mapeng)//自动识别元组元素类型
(2)元组的操作;
Ø利用_1 ,_2,_3访问元组的组元
Var v = g._1或者:var v = g _1(中间空格)
(3)利用zip方法把几个集合结合起来
scala> var one = Array(123,456)
one: Array[Int] = Array(123, 456)
scala> var two
=Array("abc","fgh")
two: Array[String] = Array(abc, fgh)
scala> var three = one.zip(two)或者使用:var three = one
zip two
three: Array[(Int, String)] = Array((123,abc), (456,fgh))//相当于生成了一个二元数组
(4)利用zip结合数组,生成映射
对应的生成一个以数组one为键,数组two为值的映射
scala> var four = one zip two toMap
scala.collection.immutable.Map[Int,String]
= Map(123 -> abc, 456 -> fgh)
1.3.5包和引用
1.4 scala面向对象
1.4.1类(class)
Scala类都是默认(public)公有可见性的,且一个文件里可以包含有多个类,省略的权限控制申明为public ;在类中申明的执行体(方法除外),在初始化对象时,都会被执行
申明一个Person类
classPerson1(name:String,varage:Int,valsex:Char) {
valscore:Int =100
//无参数的函数
defmyPrint=println("name"+name+"age:"+age+"sex"+sex)
println(“每次初始化对象时,都会被执行”)
}
Ø申明一个带有主构造器的类,包括的属性有:name;age;sex,其中:内部申明属性score
如果申明类时,没有提供主构造器,则提供默认构造器(无参数),调用默认构造器或无参方法时省略方法后面的()
ØScala类,对应属性,都会默认生成其对应的getter setter方法
l共有字段,生成的是公有的getter setter方法
l私有字段,生成的是私有的getter setter方法
l对于主构造器中的变量,其理解为:private val name:String故为私有的字段
Ø构造实例对象val person = new Person(“zhangsan”,20,”m”)
可以调用:person.myPrint//无参的方法在调用时,不能带()
Person.ageperson.sexperson.score
1.4.2构造器
1.4.1.1主构造器
classPerson1(privatevalname:String,varage:Int =0,address:String="",privatevarschool:String=""){
vargrade:Int =if(age>7)age-7else0
println(" I'm in main
constructor. ")
definfo() =" name is
"+name+", age is "+age+", address is "+address
}
Scala类有一个主构造器和多个辅助构造器,每个辅助器的名称为this,每个辅助构造器都必须用已经定义的主构造器或者辅助构造器开始定义
Ø主构造器
如果一个类没有显示的定义主构造器(主构造器的参数放置在类名之后),则有一个默认的无参主构造器
Ø对于主构造器中var
val private等标注的参数,都会成为类的对应字段,并生成对应的默认settergetter方法
Ø对于未用var val
private等标注的参数,如果类中的任何一个地方用到了该参数,则该参数会转换为类的字段,否则不会
Ø主构造器提供参数的默认值设置
Ø主构造器的函数体,是类中除了方法定义以外的其他语句,执行体在初始化对象时都会被执行
Ø初始化对象,可以只初始化主函数的前几个字段,eg:
Val person = new Person(“zhagnsan”,20)//可以通过,只是主构造器的其他参数为空
1.4.1.2辅助构造器
辅助构造器通过this来定义,且必须先使用主构造器或者其他已定义的辅助构造器;
注:辅助构造器的的参数前不能再添加val var标识,否则会报错
classPerson1(valname:String){
varage:Int =0
varaddr:String=""
println("主构造器")
//辅助构造器
defthis(name:String,age:Int){
this(name)
this.age=age
println("辅助构造1")
}
}
1.4.3对象(object)
Object用来定义某个类的单个实例
Scala中没有静态方法和静态字段,但是可以使用object语法来实现类似的功能。使用object中的常量和方法,通过类名直接调用,不用实例化;
Object的构造器不接受参数传递
1.4.3.1伴生类和伴生对象
单例对象与类同名时,这个单例对象就成为这个类的伴生对象,而这个类也成为这个单例对象的伴生类;伴生类和伴生对象要在同一个源文件中定义,伴生类可以访问伴生对象的私有成员,必须通过伴生对象.字段(方法)来访问
classPerson(valname:String) {
privatevalage=100
defadd(x:Int,y:Int) =x+y
defmyPrint=println("name:"+name+"sex:"+Person.sex)
}
objectPerson{
privatevalsex:Char ='m'
}
1.4.3.2 apply介绍
伴生对象实例化伴生类的方法
;
在伴生对象中,定义apply方法,当调用Object(obj1,obj2…)方法时,实际是调用了伴生对象的apply方法,对伴生类对象进行了实例化
classPerson(valname:String) {
privatevalage=100
defadd(x:Int,y:Int) =x+y
defmyPrint=println("name:"+name+"sex:"+Person.sex)
}
objectPerson{
privatevalsex:Char ='m'
//定义apply方法,实例化伴生对象
defapply(name:String) =newPerson(name) //实际是通过apply方法进行了对象实例化,避免了手动new对象
}
1.4.4继承
Any是整个scala继承的根,所有类都是直接或者间接的继承了Any;
extends是scala中实现继承的保留字,
Ø子类在继承超类时,必须把父类的主构造器的所有参数都填满
class Worker(name:String,age:Int,val salary:Long)extends Person1(name,age)
Ø子类继承超类所有的非私有成员;
Ø子类构造器运行在超类构造器之后;
Ø子类重写超类的成员(具有相同的名称和参数),使用override保留字进行方法、字段的重写
Ø如果类被声明为final类,则为终极类,不能被子类继承。声明为final的字段或者方法,不能被子类重写
Ø在子类中调用超类的方法,使用super.
Ø单例对象也能被继承
Ø子类的重写、修改会检查超类,但是,超类的修改并不会检查其子类
Ø重写:子类中,def只能重写超类的def,
val能重写超类的val或不带参数的def,var只能重写超类中抽象的var或者超类中的getter/setter对
1.4.4.1类型检查和转换
Ø类型检查:isInstanceOf[T]
person.isInstanceOf[Person]//检查person是不是Person类的一个实例
Ø获取对象类型
person.getClass或者:classOf[Person]
1.4.4.2保护(protected)
Ø当一个类不想被继承或者重写时,可以在该类定义时加上final关键字,代表终极类
Ø当一个类的某个方法或者字段不想被重写时,可以加上final关键字
Ø当超类中的某些成员需要被子类继承,又不想对以外成员可见时,可以在成员声明前加上protected关键字
Ø类中protected的成员对其子类可见,但对其超类不可见
1.4.4.3抽象
只要类中有任意一个为抽象成员,那么该类就必须用abstract标记;(抽象字段,是指在类中没有被初始化赋值、抽象方法,是指方法没有具体的方法实现体)
抽象类不能被实例化
重写抽象方法、抽象字段不需要使用override关键字
1.4.5特质(trait)
特质是scala里代码复用的基础单元,封装了方法和字段的定义;其定义与普通类相似,除了不能拥有构造参数;相似于java中的接口,但是特质支持部分实现,并不全是抽象
trait reset {
def reset (m : Int, n : Int) = if (m >= n) 1;
}
特质的成员可以是抽象的,并且不需要使用abstract关键字声明;
同样,重写特质的抽象方法,不用加上abstract关键字
Ø一旦特质被定义了,就可以混入到类中
class week extends reset {......}
Ø当要混入多个特质时,利用with保留字,可以实现多继承
class week extends reset with B with C {......}
特质的构造是有顺序的:从左到右被构造
u超类
u父特质
u第一个特质
u第二个特质(父特质不重复构造
u类
1.5高阶函数
函数是scala的编程的“一等公民”,函数值可以自由的被存储和传递
1.5.1匿名函数
没有函数名
(x:Int) => x*x
有名函数: