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)
}