根据视频学习的笔记:https://www.bilibili.com/video/av62245517/
===================================
变量( var ) 和 常量( val )
变量在定义的时候一定要有初始值。
val a = 12
val a:Int = 12
lazy 懒加载,调用后才会初始化,在内存中分配空间赋值
lazy val a = 12
打印
//不换行打印
print("I")
//换行打印
println("Sweet")
//c语言风格打印
printf("hello,%s! you are %d years old.\n","Fred",12)
//用的比较多的字符串插值
println(s"Hello, i'm $name, and $age years old")
println(s"Hello, i'm $name, and ${age+2} years old")
函数定义:scala函数的返回值是最后一行代码
// 最后一行为返回值
def max(a:Int,b:Int):Int={
a+b
}
//不写明返回值的类型,程序会自动判断,最后一行代码的执行结果为返回
def max(a:Int,bInt)={
a+b
}
// Unit是scala数据类型的一种,表示无值,用作不返回任何结果的方法,等同入java的void。
//省略 返回值类型 和 等于号,返回的是Unit
def max(a:Int,bInt){
a+b
}
def max(a:Int,b:Int) = a+b
空参:
//空参函数可以省略()
def myPrint() = println("hello")
def myPrint = printLn("hello")
//调用时也可以省略()
myPrint()
myPrint
* 匿名函数:
格式:(参数列表):返回类型 => {函数体}
//将匿名函数赋值一个变量
val add = (a:Int,b:Int) => a+b
//将匿名函数赋值另一个函数
def add2 = (a:Int,b:Int) => a+b
//调用
add(1,2)
默认值:
def sayHello(name:String,age:Int=20)={
println(s"Hello $name,you are $age")
}
//调用
sayHello("Jack")
sayHello("Jack",12)
变长参数:最后一位参数类型可变
def printCourse(name:String*)={
name.foreach(x => pringln(x))
}
//调用
printCourse("Java","Scala")
printCourse("Spark")
带名传参,打乱顺序传递参数,不常用
def sayHello(firstName:String,middleName:String,lastName:String)={
println(firstName+"."+middleName+"."+lastName)
}
//调用
sayHello("Monkey",lastName="Luffy",middleName="Lucy")
Scala中没有 break 和 continue
def main(args:Array[String]):Unit={
var a = 0
val numList = List(1,2,3,4,5,6)
//创建一个Break实例对象
val loop = new Breaks
loop.breakable{
for( a <- numList){
println("Value of a:"+a)
if( a == 4) {
loop.break()
}
a+=1
}
}
println("中断循环")
}
Range : 左闭右开 [)
Unitl : 左闭右开 [)
To :左闭右闭 []
1 to 10 // 1.to(10) , Range(1,2,3,4,5,6,7,8,9,10)
1.until(10)// 1 until 10 , Range(1,2,3,4,5,6,7,8,9)
Range(1,10)//Range(1,2,3,4,5,6,7,8,9)
Range(1,10,2)//可以指定步长 Range(1,3,5,7,9),步长不能为0
Range(10,1,-1)//Range(10,9,8,7,6,5,4,3,2,1)
for 循环
for( i <- 1 to 10){}
var n = 10
for(i <- 1 to n){}
//可以对字符串遍历
for(i <- "HELLO"){}
//for循环结合if守卫:取偶数
for(i <- 1 to 20 if i%2 == 0) println(i)
//双重循环
for(i <- 1 to 9;j <- 1 to i){
if(i == j) print()
else print()
}
for(i <- 1 to 9){
for(j <- 1 to i){}
}
元组
//定义元组:()里面包含一系列的值
val a = (1,2,3,4)
//取值
a._1
a._2
a._1 = 3 //error:元组不能重新赋值
val b = ("lisa",(21,"female")) // b:(String,(Int,String)) = ("lisa",(21,"female"))
//获取其中的female
b._2._2
//遍历
for( i <- 0 until a.productArity) println(a.productElement(i))
var (a,b) = (11,"hello") // 此非元组,是多个变量同时赋值
//Ps:元组的命名由其内部的元素个数决定,比如二元组,五元组...元组没有1元组,最多支持22元组
数组
//定长数组
val a = new Array[String](5) // Array[String] = Array(null,null,null,null,null)
a.length // Int = 5
a(0) = "pol"
//不用new
val b = Array("aaa","bbb") //索引 0,1,2
b(1) // bb
//变长数组
val c = scala.Collection.mutable.ArrayBuffer[Int]()
c += 1 //ArrayBuffer(1)
c += 2 //ArrayBuffer(1,2)
c += (3,4,5) //ArrayBuffer(1,2,3,4,5)
c ++= Array(6,7,8) // ArrayBuffer(1,2,3,4,5,6,7,8),也可以 ++= ArrayBuffer(6,7,8)
c.remove(1) //ArrayBuffer(1,3,4,5,6,7,8)
c.remove(0,3) //ArrayBuffer(5,6,7,8),从索引0开始,删除3个
c.insert(0,4) //ArrayBuffer(4,5,6,7,8)
c -= 6 //顺序找到第一个6删除,只删除一个
//变成定长数组
c.toArray
//移除最后两个
c.trimEnd(2)
//循环
for( i <- 0 until c.length) println(c(i))
for( ele <- c) prinln(ele)
//排序
scala.until.Sorting.quickSort(c)
//将数组转换成字符串
c.mkString( " and ")
c.mkString("(" , "," , ")")
//总和,最大,最小
c.sum
c.max
c.min
集合之List
//Nil是空的list
Nil //scala.collection.immutable.Nil.type = List()
//List 由 Nil 或者 head +tail 构成,其中 tail 又是一个 List
val li = List(1,2,3,4,5)
li.head //Int = 1
li.tail //List[Int] = List(2,3,4,5)
//添加到Nil集合的最前面
val li2 = 1 :: Nil //List(1)
val li3 = 2 :: li2 //List(2,1)
//构建: List(1,2,4) 等价于 1::2::3::Nil ,从左到右运算
val li4 = 1 :: 2 :: 3 :: Nil //List(1,2,3)
val li5 = scala.collection.mutable.ListBuffer[Int]()
li5 += 2
li5 += (3,4,5)
li5 ++= List(6,7,8,9)
//List中常见方法:recerse,contains,distinct,exists,filter,length,max,min
集合之Set:无序不重复
+/++/-/-- 都会创造一个新的Set
+=/++=/-=/--= 不会创造一个新的Set
val s = Set(1,2,3,4)
//返回新的Set,需要变量接收
s + 5
s + 5 + 6 + 7
s + (5,6,7)
s ++ List(5,6,7)
s - 1
s - (1,2,3)
s -- List(1,2,3)
s -- Array(1,2,3)
val s3 = scala.collection.mutable.Set(1,2)
//返回新的Set
s3+3
s3+=3
//有序Set
val s2 = scala.collection.imutable.SortedSet(2,1,4,2)
集合之Map
//不可变Map
val a = Map("zhangsan" -> 22,"lisi" -> 21)
//可变Map
val b = scala.collection.mutable.Map("zhangsan"->22,"lisi"->21)
val c = scala.collection.mutable.Map[String,Int]()
//联通map(key),更好的方式map.getOrElse(key,default)
a("张三") // 27
a("abc") //exception
a.getOrElse("XX",10) // 10
//更新map操作 : map(key)=value / +- / --
b("spring") = 6
b("spring") // 6
b += ("bb" -> 4, "cc" -> 6)
b -= ("bb")
//for循环
for( (i,j) <- b){
println("key: "+ i +" value :"+j)
}
for(ele <- b.keySet){
println("key : "+ ele + " value : "+ b.getOrElse(ele,0))
}
for(ele <- b.value){
println("value is " + ele)
}
for( (key,_) <- b){
println("key is "+key + " value is "+ b.getOrElse(key,0))
}
//排序
scala.collection.immutable.SortedMap("zhangsan" -> 22,"lisi" -> 21)
get,set 方法
class Person{
private var privateName = "" //需要默认值
//getter方法
def name = this.privateName
//setter方法
def name_=(name:String):Unit={
this.privateName = name
}
}
//调用
a.age = 23 //此时会自动调用set方法
a.age_=(23)
println(a.age)
/*
*默认生成的getter 和 setter 方法限制
* 1 如果字段是私有的,则getter和setter方法也是私有的
* 2 如果字段是val,则只有getter方法
* 3 如果你不需要任何 getter 和 setter方法,可以将字段声明为private[this]
*/
构造器:有且只有一个主构造器,可以有多个辅助构造器(辅助构造器用this命名)
//主构造器为空参构造
class Phone{
private var name
private var brand
//辅助构造器
def this(name:String){
this()
this.name = name
}
//另一个辅助构造器,需要调用主构造器 或者其他 已有的构造器
def this(name:String,brand:String){
this(name)
this.brand = brand
}
}
//主构造器为有参构造
class Phone(var newName:String){
}
伴生类 和 伴生对象
1 如果有一个class,还有一个与class同名的object,那么就称这个object是class的伴生对象,class是object的伴生类
2 伴生类和伴生对象必须存放在一个.scala文件中
3 伴生类和伴生对象,最大的特点就在于,相互可以访问private field
class Person{
private var userName
def getUserName = userName
def printInfo = println(
s"hello, i am $userName, i have ${Person.eyes} eyes"
)
}
object Person{
private var eyes = 2
def getEyes = eyes
}
object 中一个非常重要且特殊的方法 : apply
通常在伴生对象中实现apply方法,并在其中实现构造伴生类的对象的功能,而创建伴生类的对象时,通常不会使用new Class的方式,而是使用Class()的方式,隐式地调用伴生对象的apply方法,这样会让对象创建更加简洁
class Person(val name:String){}
object Person{
def apply(name:String) = new Person(name)
}
//调用不需要new
val p = Person("lili")
val arr = Array(1,2,3)
Trait : 可以将Trait作为接口来用
trait 中可以定义抽象方法,能与抽象类中的抽象方法一样,只要不给出方法的具体实现即可
类可以使用 extends 关键字继承trait,注意,这里不是implement,而是extends,在scala中没有implement的概念,无论继承还是trait,统一都是extends
类继承trait后,必须实现其中的抽象方法,实现时不需要使用override关键字
Scala不支持对类进行多继承,但是支持多重继承trait,使用with关键字即可
trait Alarm{
def alarm():Unit
}
abstract class Door{ // 或者 trait Door
def open():Unit
}
class SecurityDoor extends Door with Alarm{
override def open():Unit={
println("open the door")
}
override def alarm():Unit={
println("Some body breaking in")
}
}
//测试
var door = new SecurityDoor
door.alarm()
高阶函数 : 接收其他函数作为参数的函数,被称为高阶函数
高阶函数的另外一个功能是将函数作为返回值
a 高阶函数可以自动推断参数类型,而不需要写明类型;
b 对于只有一个参数的函数,还可以省略小括号
c 如果仅有一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_来代替
val sayHelloFunc = (name:String) =>println("Hello "+name)
def greeting(func:(String) => Unit, name:String){func(name)}
greeting(sayHelloFunc,"leo")
//Array的map
Array(1,2,3,4,5).map((num:Int) => num*num)
Array(1,2,3,4,5),mao((num) => num*num)
Array(1,2,3,4,5),mao(num => num*num)
Array(1,2,3,4,5).map((num:Int) => num.toString)
Array(1,2,3,4,5).map(_.toString)
//将函数作为返回值
def getCreetingFunc(msg:String) = (name:String) =>prinln(msg + ","+name)
val greetingFunc = getGreetingFunc("hello")
greetingFunc("张三")
Scala的常用高阶函数
//map:对传入的每个元素都进行映射,返回一个处理后的元素
Array(1,2,3,4,5).map(_*2) //2,4,6,8,10
//foreach:对传入的每个元素都进行处理,但是没有返回值
(1 to 9).map("*" * _).foreach(println _) //第一行一个*,第二行2个*...以此类推的三角形图形
//filter:对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素
(1 to 20).filter(_%2 == 0)
//reduceLeft: 从左侧元素开始,进行reduce操作,即先对元素1 和 元素2 进行处理,然后将结果与元素3处理,再将结果与元素4处理,以此类推。即为reduce。
(1 to 9).reduceLeft(_*_)
//flatten 扁平化,降维
//eg: Array(Array("e","a"),Array("e","a")) => Array("e","a","e","a")
Array("hel o","h w","you").map(_.split(" ")).flatten
//groupBy:分组,定义规则,规则为key,相同规则的为一组,返回类型为map
Array("hel o","h w","you").groupBy(_.charAt(0))
//flatMap: 集合map和flatten
Array("hel o","h w","you").flatMap(_.split(" "))
//sortBy
Array("asda","kdj","asadj").sortBy(_.size)
Array("asda","kdj","asadj").sortBy(_.charAt(0))
闭包: 是一个函数,返回值依赖于声明在函数外部的一个或多个变量
闭包通常来讲可以简单的任务是可以访问一个函数里面局部变量的另外一个函数。
//匿名函数
val mult = (i:Int) => i*10
//函数里有一个变量
var factor = 3
val mult = (i:Int) => i* factor
柯里化:是一种新技术,把接收多个参数的方法变换成接收一个单一参数的函数,并且返回剩下的参数的新函数
//原始多参数
def sum(x:Int,y,Int) = x + y
//柯里化
def sum(x:Int)(y:Int) = x + y
//调用
sum(1)(2)
Array(1,2,3,4,5).foldLeft(0)((a,b) => a+b)
//可以简写为以下形式
Array(1,2,3,4,5).foldleft(0)(_+_)
Array(1,2,3,4,5).foldLeft(0)(_+_)
Array(1,2,3,4,5).reduce( _ + _ )
模式匹配,类似java的case。除了可以匹配值,scala还可以匹配类型,甚至对有值或没值进行匹配.可以加if守卫
//值匹配
def judgeGrade(grade:String){
grade match{
case "A" => println("very good")
case "B" => println("good")
case "C" => println("just so so")
case _if grade.size == 0 => println("byebye")
case _ => prinln("hahahaha")
}
}
//类型匹配
def processException(c: Exception){
c match{
case e1:FileNotFoundException => println("..." + e1 )
case e2:IOException => println("....." + e2 )
case _:Exception => println("........" + _)
}
}
//Array 和 List 匹配
// Array模式匹配:分别可以匹配 带有指定元素的数组 , 带有指定个数元素的数组, 以某元素打头的数组
// List模式匹配: 与Array类似,但是需要使用List特有的::操作符
def greeting(arr:Array[String]){
arr match{
case Array("Leo") => println("带有指定元素的数组")
case Array(g1,g2,g3) => println("带有指定个数的数组:"+g1+g2+g3)
case Array("Leo",_*) => println("以leo打头的数组")
case _ => prinln("没啦")
}
}
def greetingList(list:List[String]){
list match{
case "Leo"::Nil => println("带有指定元素的数组")//只有一个Leo元组的List
case g1::g2::g3::Nil => println("带有指定个数的数组:"+g1+g2+g3)
case "Leo"::tail => println("以leo打头的数组")
case _ => prinln("没啦")
}
}
//Tuple 和 字符串的匹配
def match_tuple(tuple:Any) = tuple match{
case (0,_) => println("第一个元素是0,第二个元素任意类型")
case (x,0) => println("第一个元素是任意类型,第二个元素是0")
case _ => println("other")
}
"Hello World" foreach(c => println(
c match{
case '' => "Space"
case ch => "Char:"+ch
}
))
样例类,相当于java中的JavaBean,只定义属性,并且由Scala编译时自动提供getter和setter方法,但是没有其他的method
默认参数使用val修饰
自动为case class 定义伴生对象object,并且定义了apply()方法
class Person
case class Teacher(name:String,subject:String) extends Person //case Class:样例类
case class Student(name:String,classroom:String) extends Person
//匹配类
def judgeIdentity(p:Person)={
p match {
case Teacher(name,subject) => println("you are a teacher :"+name)
case Student(name,classroom) => println("you are a student:"+name)
case _ => println("i don't know")
}
}
Scala中有一种特殊的类型:Option,有两种值:Some(有值),None(没有值)
val grades = Map("Leo"-> "A","Marry"->"B")
def getGrade(name:String)={
// grades.get(name)获得的 是否有name这个key,获得value:grades.get(name).get
val grade = grades.get(name)
grade match {
case Some(grade) => println("your grade is "+ grade)
case None => println("nothing")
}
}
隐式转换 : 核心是定义隐式转换函数,即implicit conversion function .在程序中使用到隐式转换函数接收的参数类型定义的对象时,会自动将其传入隐式转换函数,转化为另外一种类型的对象并返回
//特殊售票口(只接收特殊人群,比如老人,学生等)
//类
class SpecialPerson(val name:String)
class Student(val name:String)
class Older(val name:String)
//隐式转换
implicit def object2SpecialPerson(obj:Object):SpecialPerson = {
if(obj.getClass == classOf[Student]){
val stu = obj.asInstanceOf[Student]
new SpecialPerson(stu.name)
}else if(obj.getClass == classOf[Older]){
val older = obj.asInstanceOf[Older]
new SpecialPerson(older.name)
}else Nil
}
//调用
def buySpecialTicker(p:SpecialPerson) ={
ticketNumer+=1
println("T : "+ticketNumber)
}