0. Scala简介
- 多范式
- 类似java, 可调用Java类库, 运行于JVM
- 初衷是实现可伸缩的语言
- 集成面向对象编程和函数式编程的各种特性
- IDE选择idea
1. 入门
支持的数据类型
Scala中不存在基础数据类型,一律以类的形式出现
数据类型 |
含义 |
Byte |
8位整数,-128~127 |
Short |
16位整数,-32768~32767 |
Int |
32位整数, -2147483648~2147483647 |
Long |
64位整数, -9223372036854775808~9223372036854775807 |
Float |
32位浮点数 |
Double |
64位浮点数 |
Char |
16位Unicode字符 |
String |
字符序列 |
Boolean |
布尔 |
Unit |
空,同void,打印出() |
Null |
null |
Nothing |
任何类的子类 |
Any |
任何类的超类 |
AnyVal |
任意常量类 |
Java类 |
可以通过import导入Java类库,引入Java数据类型如java.util.Date |
BigInt |
math类下的子类,整数 |
BigDecimal |
math类下的子类,数值型 |
基础语法
代码 |
功能 |
var x:Int=1 |
定义一个可修改的变量x=1,类型为Int |
val y=2 |
定义一个不可修改的常量y=2,类型由系统自己推断 |
printf(“x:%d”,x) |
格式化打印,d数字,s字符串,f浮点数 |
var x,y=8 |
同时赋值8给x和y两个变量 |
x=x+1,x+=1,x.+(1) |
等价,不支持x++ |
1 to 10 |
由1到10组成的集合 |
1 until 10 |
由1到9组成的集合 |
_ |
表示全部,相当于* |
import math._ |
导入math类下所有子类 |
“hello”.apply(1) |
将字符串看作集合,按索引1获取字符 |
“hello”.reverse |
字符串反转 |
var x:BigInt=BigInt(“99999999999999999”) |
通过BigInt方法转换字符串突破整数长度限制 |
var x=StdIn.readInt() |
标准输入获取Int赋值给变量x |
var r=Random.nextInt(20) |
获取在0到20间的随机数 |
(x:Int,y:Int):Int=>x+y |
推导 |
2. 数组
定长数组Array
var arr1=Array(1,2,3)
var arr2=New Array[Int](3)
for(i<-arr1.indices)print(i)
arr1(0)=10
var amax=arr1.max
var alen=arr1.length
var aarr=arr1.map(_+1)
arr1.foreach(printf _)
var newarr=arr1.filter(_%2==0)
var carr=concat(arr1,arr2)
var sarr=arr1.sorted
var sarr="aaa aa a aaaa".split("\\s").sortWith(_.length < _.length )
var res=arr1.reduceLeft(_*_)
var flag=arr1.corresponds(arr2)(_.equals(_))
var a1=1 to 5
var a2=2 to 6
var a3=a1 zip a2
变长数组ArrayBuffer
var arr=new ArrayBuffer[Int]()
arr+=(1,2,3)
arr.insert(0,10,20)
arr++=ArrayBuffer(4,5,6)
arr.trimStart(2)
arr.trimEnd(2)
arr.remove(0)
3. 函数
- 简单函数的一般形式
def 函数名(参数:类型):返回类型=函数体
- 函数的调用
Object名.函数名()
- 匿名推导函数
(x:Int,y:Int):Int=>x+y
(x,y)=>x+y
基本函数
def madd(x:Double,y:Double)=x+y
def fsum(x:Int*)=(for(i<-x)yield i).sum
def func1(pname:String="ghy",page:Double=28)=println(pname+page)
var sumarr=fsum(arr:_*)
可变函数
var f1=fsum _
f1=func1 _
高阶函数
//定义一个函数,其中参数为匿名函数,可给定参数值
def dou(f:(Int)=>Int)=f(5)//对于传入的函数规定了参数类型,返回类型,参数的初始值为5
//调用该函数时要传入符合要求的另一个函数
var res=dou(x=>x+1)//参数为匿名函数(参数为x,函数体x+1,类型由系统推断)
//在数组中调用自定义函数
def fang(n:Double)={
var res=math.pow(n,n)
println(res)
}
(1 to 5).foreach(fang(_))//foreach表示遍历数组但不yield结果,调用fang函数传入_每个元素
闭包函数
- 定义的函数返回另一个函数,包装返回中的函数叫闭包
- 使用函数设计模式,导致闭包的函数能够在非作用域也能够被调用
//函数体中包含函数
def b1(x:Int)=(y:Int,z:Int)=>y*z+x
//调用函数返回闭包函数
var f1=b1(10)
var res=f1(10,10)
函数的柯里化
- 将多个参数转变为高阶函数形式的多个单参数函数的过程
- 便于使用lambda表达式
def add(x:Int,y:Int)=x+y
def add1(x:Int)=(y:Int)=>x+y
def add2(x:Int)(y:Int)=x+y
var res1=add1(10)
var r1=res1(5)
var res2=add2 _
var r2=res2(5)
var r3=r2(10)
println(r1,r3)
菲波那切数列
//定义一个函数fec,递归必须指定返回类型Int
def fec(n:Int):Int=if (n==0) 0 else if (n==1) 1 else fec(n-1)+fec(n-2)
//调用函数fec,循环打印前10个数
for(i<1 to 10)print(fec(i)+"\t")
4. 控制语句
while
var x=0
while(x>10){
print(x)
x += 1
}
if
var s=if(x>10) "yes" else if (x<5) "no" else "ok"
for
var s=for(i<-1 to 10)yield i
for(i<-1 to 5;j<-1 to 5 if i==j)printf("i:%d,j:%d",i,j)
for(i<-(1 to 10).reverse)print(i)
杨辉三角
var martix=Array.ofDim[Int](6,6)
for (i<-martix.indices;j<-0 to i)if (i==0|j==0|i==j) martix(i)(j)=1 else martix(i)(j)=martix(i-1)(j-1)+martix(i-1)(j)
for (i<-martix.indices;j<-0 to i){printf("%4d",martix(i)(j));if (i==j)println()}
5. 集合
分类
- 可变集合,支持修改扩展元素
- 不可变集合,修改后会返回新集合,不影响原集合
集合类型 |
特点 |
常用 |
Seq |
保证插入顺序,可重复 |
IndexedSeq |
Set |
不保证顺序,不可重复 |
SortedSet |
Map |
键值对,排序时按键排序 |
SortedMap |
Vector |
树形结构的索引序列,不可变 |
1 to 10 |
Range |
索引序列 |
Range 1 to 10 |
列表 |
Seq序列,元素类型相同,不可变 |
List |
元组 |
小括号形式 |
(1,”one”) |
迭代器 |
可迭代 |
iterator |
6. 类和对象
- 类class和对象object区别在于class必须new生成内存才能使用,object可直接通过变量调用
- 类的参数可分为var变量声明和普通参数,var声明后则作为类的属性包含getset方法
- class和object名相同时形成伴生对象,其中类可以调用对象,对象不可调用类,对象仅作为类的辅助存在
- 内部类和外部类在实例化时,必须先实例化外部类,以val方式
类的参数var
class Stu(var sname:String,sex:String) {
println("我是构造方法中的语句")
val xage=8
def this(age:Int){
this("ghy","man")
println("我是一个参数的构造方法")
}
def say=println("say...")
override def toString: String = "你叫"+sname
}
object ok{
def main(args: Array[String]): Unit = {
var x=new Stu(77)
x.sname="吕布"
println(x)
}
}
内部类和外部类=>
class myOuter(var oname:String){
myouter=>
class myInner(var iname:String){
println("内部类的构造方法:"+myouter.oname)
}
}
object demo02{
def main(args: Array[String]): Unit = {
val x=new myOuter("outer")
val y=new x.myInner("inner")
}
}
提取器方法unapply
object RichFile{
def unapply(input: String)={
val data=input.split("/")
if(data==null)
None
else
Some(data(data.length-1))
}
}
object a10{
def main(args: Array[String]): Unit = {
val file="/home/cay/readme.txt"
val RichFile(x)=file
println(x)
}
}
单例模式object
//单例模式,可以用object直接写一个对象,调用时就是单例的
object Singletondemo {}
object AppTest3{
def main(args: Array[String]): Unit = {
var s1=Singletondemo
var s2=Singletondemo
//调用多次只生成一块内存
println(s1+"\n"+s2)//地址相同
}
}
工厂模式apply…match case …=>
abstract class Animal
object Animal{
def apply(stype:String): Animal = stype match {
case "cat"=>new Cat
case "dog"=>new Dog
case _=>new Pig
}
}
class Cat extends Animal{println("cat...")}
class Dog extends Animal{println("dog...")}
class Pig extends Animal{println("pig...")}
object a2{
def main(args: Array[String]): Unit = {
val x=Animal("cat")
}
}
WordCount练习
val str=Source.fromFile("e:/1.txt").mkString.split("\\s")
var ma=str.map((_,1)).groupBy(_._1)
var li2=ma.map(w=>(w._1,w._2.size)).toList.sortBy(_._2).reverse
var wr=new PrintWriter("e:/2.txt")
for(i<-li2)wr.write(i._1+"->"+i._2+"\n")
wr.close()
模式匹配多种类型Any
def main(args: Array[String]): Unit = {
var s=match01("two")
println(s)
}
def match01(x:Any)={
x match {
case 1 =>"one"
case _:Int=>"Int"
case "two"=>2
case _:String=>"String"
}
}
伴生对象object …class
class 伴生 {
var xname:String="雷霆"
def say={
printf("say.....%d\n",伴生.xage)
println(f"xname:$xname")
伴生.two
}
}
object 伴生{
var xage:Int=8
def two()={
println("比利时VS日本")
}
}
object demo{
def main(args: Array[String]): Unit = {
val x=new 伴生
x.say
}
}
7. 其他
捕获异常
- 通过try catch case捕获
try {
var x=1/0
}catch {
case _:ArithmeticException=>println("除数不能为0")
case _:Exception=>println("全部错误")
}
迭代器
- 通过序列方法iterator返回迭代器
val x=1 to 5
var it=x.iterator
while (it.hasNext){
val v=it.next
println(v)
}