一,变量
1,基本数据类型
2,基本运算符
3,定义变量
4,复杂变量
(1)定义数组Array:
- 声明:val aList=new Array[数据类型type](n):声明存储数据类型为type的n个对象,数组初始化为null
- 声明:val aList=Array(n1,n2,n3...):声明时,可以不用声明数据类型。
- 调用:aList(m):调用第m个元素。
- 声明多维数组:val aList=Array.ofDim[数据类型](a,b):声明行为a,列为b的二维数组
- 调用多维数组中的元素:aList(a1)(b1):调用数组中行为a1,列为b1的元素
(2)定义元组Tuple(对多个不同类型的对象的简单封装):
- 声明: val tStudent=("name1",23,"男",560.00):声明元组类型学生的信息为(姓名,年龄,性别,月开销)
- 调用:tStudent._1(取出"name1");tStudent._2(取出23);tStudent._3(取出"男")....
(3)定义容器Collection(导包scala.collection;scala.collection.mutable;scala.collection.immutable)
scala.collection:封装了可变容器和不可变容器的通用操作的超类(从上到下依次继承都是特质(类似Java的接口),不是具体的容器)
foreach方法:遍历当前容器内所有元素
(4)定义序列Sequence(如上图Seq有两个子序列:IndexedSeq和LinearSeq)有存入数据有先后顺序,可以重复
LindearSeq:列表和队列可以继承该类
List(列表):具体的容器类,列表内的对象必须是同类型,列表内的值不可变(必须导包scala.collection.immutable)
定义:val slPeople=List("张三","李四","王五"......)
头部:head;尾部:tail 获取头部(第一个元素:slPeople.head);获取尾部(除去第一个元素以外的元素:slPeople.tail)
向列表头添加新的元素从而生成新的列表:val slNewList="赵四"::slPeople(不能给列表的尾添加元素)
Range(队列):是一种特殊的带索引的不可变数字等差序列(range内可以存放任何类型数据)
定义:val irNum=new Range(n1,n2,m):与Python的range函数功能相同,n1(开始量)n2(结束量,取不到)m(步长)
1 to 8 by 1:得到包括8的Range(1,8,1)序列
1 until 8 by 1:得到Range(1,8,1)序列
IndexedSeq:Vector和ArrayBuffer可以继承该类
Vector(向量):
定义:val svPeople=Vector("张三","李四","王五"......)
获取元素svPeople(n):获取第n+1个元素
向Vector的头添加元素:svPeople1="赵四"+:"钱七"+:svPeople;向Vector的尾添加元素:val svPeople2=svPeople:+"孙八"
(5)定义集合Set:存放不重复元素,没有先后顺序,用哈希方法去查找元素(默认为不可变集合)
可变集:(导包scala.collection.mutable)
不可变集:(导包scala.collection.immutable)
import scala.util.control.Breaks._; import scala.collection; import scala.collection._; import scala.collection.immutable._; var ssPeople=Set("张三","李四"); //Set("张三","李四")是不可变集,将不可变集赋给可变变量ssPeople ssPeople+="王五"; //将"王五"赋加给变量ssPeople后生成新的不可变集Set("张三","李四","王五") import scala.collection.mutable._; //要定义可变集必须导入这个包 val ssPeople1=Set("张三","李四"); //Set("张三","李四")是可变集, ssPeople1+="王五";
(6)定义映射Map:一系列键值对的容器,键唯一但值不唯一(默认为不可变映射)
可变映射:(导包scala.collection.mutable)
不可变映射:(导包scala.collection.immutable)
import scala.util.control.Breaks._; import scala.collection; import scala.collection._; import scala.collection.immutable._; var ssPeople=Map("姓名:"->"张三","年龄:"->16); //不可变映射 import scala.collection.mutable._; //要定义可变集必须导入这个包 val ssPeople1=Map("姓名:"->"张三","年龄:"->16); //Set("张三","李四")是可变映射, ssPeople1+=("性别"->"男","学号:"->20173522); //向可变映射中添加多个元素 ssPeople1("姓名:")="李四"; //更新可变映射中的元素 ssPeople1("学校:")="石家庄铁道大学"; //向可变映射中添加单个元素 print("查询姓名"); var result=if(ssPeople1.contains("姓名:")) ssPeople1("姓名:") else "无法查询姓名" //当映射中存在键为"姓名:"则将对应的值赋给result,否则将无法查询xx赋给result print(s"姓名:$result");
二,输入,输出
1,从控制台输入(导包:scala.io.StdIn):
2,输出(默认导包scala.Predef):
(1)类Java的输出方式: print("姓名:"+name+" 年龄:"+age)或println("姓名:"+name+" 年龄:"+age)
(2)类C的输出方式:printf("姓名:%s 年龄:%s",name,age)
(3)s插值字符串输出法:print(s"姓名:$name 年龄:$age")
(4) f插值字符串输出法(格式化):
三,读写文件(导包java.io.PrintWriter和scala.io.Source)
1,写入(导包java.io.PrintWriter):向文件test.txt中写入信息:
2,读取(导包scala.io.Source):
四,控制结构
1,for结构:
用法一:基本结构
用法二:for结构中加条件
用法三:支持多个生成器,用;隔开
用法四:将遍历的值付给变量
2,异常处理(try......catch.....)
3,循环控制(不存在break和continue终止循环)
使用Breaks类(导包scala.util.control)
当使用breakable方法:
import scala.util.control.Breaks._; var i=0; val array=Array(1,3,6,15,9,12,16); breakable{ //这个大括号不能换行 for(i<-array) { if(i>10) break; //循环到15直接跳出循环 print(i+" "); } }
4,判断值是否存在:contains()
五,类
1,定义方法:当有返回值,则返回String,Int,Boolean;无返回值,则返回Unit类型
参数列表中的参数不能用val,var修饰
参数列表没有时,可以不用()
(参数列表)可以写成{参数列表};当只有一个参数时,可以用中缀调用法
当方法体只有一条语句,可以省略{}
import scala.util.control.Breaks._; class Conent{ //不能换行 var value=0; def dIncrement(s:Int):Unit={ value+=s; } def dCurrent():Int={ value; } } val conent=new Conent; conent.value=5; conent.dIncrement(2); print(conent.dCurrent);
2,类似Java的get,set方法:value方法相当于Java的Getxx方法,获取类中的变量的值;value_方法相当于Java的Setxx方法,修改类中变量的值。
import scala.util.control.Breaks._; import scala.io.StdIn; class Student{ private var pvsName=""; private var pviAge=0; def valueName=pvsName; def valueName_=(newName:String){ pvsName=newName; } def valueAge=pviAge; def valueAge_=(newAge:Int){ if(newAge>0 &&newAge<200){ pviAge=newAge; } } } val students=new Student; printf("请输入姓名:"); var sname=readLine(); students.valueName_=(sname); printf("请输入年龄:") var iage=readInt(); students.valueAge_=(iage); printf("学生姓名:%s 学生年龄:%d",students.valueName,students.valueAge);
六,构造器
主构造器:scala可以定义带参数的类作为一个主构造器,可以给这个类之间传参,改变参数值,输出参数值
辅助构造器:调用形式:this(参数列表)
import scala.util.control.Breaks._; import scala.io.StdIn; class Student{ var sName=""; var age=0; println("这是主构造器;"); def this(sName:String){ //第一个辅助构造器 this(); //调用主构造器 this.sName=sName; print(s" 这是第一个辅助构造器;姓名:$sName "); } def this(sName:String,age:Int){ //第二个辅助构造器 this(sName); //调用第一个辅助构造器 this.age=age; print(s" 这是第二个辅助构造器;姓名:$sName 年龄:$age "); } } var getStudent=new Student("张三"); //执行第一个辅助构造器 var getStudent=new Student("张三",17); //执行第二个辅助构造器
运行结果:
(七)对象
1,单例对象:1,定义,使用object定义;object 对象名{ 内容}
2,对象内的所有字段和方法都是静态的,不用对对象的进行实例化。
3,分类:伴生对象和孤立对象
1,伴生对象:当类名和单例对象名一样且定义在一个scala代码文件中,则彼此可以访问对方的成员
2,孤立对象:一个scala代码文件内类名和单例对象名都不相同,则这个单例对象称为孤立对象,
2,apply方法:不断创建对象,自动调用(工厂方法);例如创建数组时,直接val array=Array(“张三”,"李四"),会自动调用apply方法。
当要调用的类中定义了apply方法,则不用手动调用apply方法,程序会自动调用该方法。
将面向对象编程(调用方法:对象.方法(参数))和函数式编程(方法(参数))结果一致,都可以使用
对象调用可以转换为函数调用;函数调用可以转换为对象调用
例子:使用伴生对象,伴生类和apply方法
import scala.io.StdIn; class Student(name:String,age:Int){ def Test():Unit={ print(s"姓名:$name,年龄:$age "); } } object Student{ def apply(name:String,age:Int)=new Student(name,age); //调用伴生类的构造方法 } object Main{ def main(args: Array[String]): Unit = { println("请输入姓名:"); var name=readLine(); println("请输入年龄:"); var age=readInt(); var student=Student(name,age); //调用伴生对象的apply方法 student.Test(); } }
运行结果:
3,update方法:根据对象名取出对象的参数;要使用对象参数时调用。
(八)类的继承
1,抽象类:类的成员没有被实例化,用abstract修饰;
在抽象类中可以定义有方法体,被实现的方法。
抽象类中的成员,方法不用abstract修饰;但抽象的变量必须声明类型:val name:String;
2,继承类:必须加extends关键字;
子类只能重载val变量
如果父类中的变量已经赋值,子类调用父类变量则要加override,如果父类中的变量没有赋值,子类调用父类变量则可以不加override
3,option类:抽象类,对象:Some对象(返回不为空时,封装到该对象)和None对象(返回为空时)
4,特质:有Java的接口功能,但可以在特质中定义有方法体的方法;关键字:trait
特质中定义抽象方法可以不用abstract关键字
特质可以继承特质
一个类可以混入多个特质,关键字:extends 特质名1 with 特质名2
5,模式匹配:
1,类似switch()..case:...:不需要break退出
var grade=readChar(); grade match { case 'A' =>println("85-100"); case 'B' =>println("75-84"); case 'C' =>println("60-74"); case 'D' =>println("30-59"); case _=> println("对不起,你输错了") }
例子:case可以判断数据类型 case后可以加入判断
2,case类:自动重载多个有用对象,自动创建伴生对象(apply方法和unapply方法)。
6,包:可以嵌套定义。
(九)函数:
1,定义:
2,函数字面量:
函数类型和值:
类型:
值:
3,另一种定义函数方式:函数式变量可以调用,可以赋给其他变量(函数名counter可以省略,匿名函数又称Lambda表达式)
当函数中变量只出现一次,可以用_占位
4,高阶函数:函数的一个参数为另一个函数
(十)对容器操作:
1,遍历操作:foreach方法:容器名.foreach(参数)
例子:变量映射:
2,映射操作:
例如:对容器元素进行一对一映射操作;关键操作函数:map(具体操作方法)
将得到的三个结果容器拍扁成为一个容器;关键操作函数:flatMap(具体操作方法)
3,过滤操作:关键操作函数:filter(具体过滤操作)
例如:将Map中值含有"三"的键值对留下:
4,归约操作:关键操作函数:reduce(具体操作)
归约函数使用了s插值输出方式
使用fold方法,可以赋初始值;