学习笔记—scala高级编程

来源:互联网 发布:易语言模块转源码 编辑:程序博客网 时间:2024/06/08 04:34

函数式编程

  • scala 中函数可以独立存在,不需要依赖任何类和对象
  • 将函数赋值给变量 
    使用def定义方法和函数 
    函数,方法的区别是出现的位置不同,在类里面是方法 ,在类外是函数
  1. //将函数赋值给变量时,必须在函数后加上空格和下划线
  2. def say(name:String) {println("hello"+name)}
  3. val sayFunc=say _
  4. sayFunc("leo")
  • 匿名函数 
    没有名字的函数称为匿名函数 
    可以直接定义函数后将函数赋值给某个变量,也可以将匿名函数传入其它函数中 
    定义匿名函数的语法规则:(参数名:参数类型)=>函数体
  1. //匿名函数
  2. val aa=(name:String)=>println("hello"+name)
  • 高阶函数 
    接受其他函数作为参数的函数称为高阶函数
  1. 可以直接将某个函数作为参数传入其他函数
  2. 将函数作为返回值
  1. //将函数作为参数
  2. val say=(name:String) => println("hello"+" "+name)
  3. def greeting(func:(String) => Unit,name:String){func(name)}
  4. greeting(say,"Tom")
  5. //将函数作为返回值
  6. def getGreetingFunc(msg:String)=(name:String)=>println(msg+","+name )
  7. val greetingFunc=getGreetingFunc("hello")
  8. greetingFunc("leo")

Map和faltMap的区别

  1. lines.map(x=>x.split(" ")).collection
  2. //faltMap:faltten Map ,先执行map,后执行flatten(扁平化)
  3. lines.flatmap(x=>x.split(" ")).collection
  4. //
  5. line.map(x=>x.split(" ")(2) ) //取新形成数组的索引为2 的值
  6. lines.first //只取第一条数据
  • 高阶函数的类型推断 
    高阶函数可以自动推断参数类型,不需要写明类型 
    如果函数只有一个参数,可以省略小括号
  1. greeting ((name:String)=>print("hello"+ " "+name),"tom")
  2. greeting (name=>print("hello"+ " "+name),"tom")
  • scala的常用高阶函数
  1. //map对传入的每一个元素进行映射,返回一个处理后的结果
  2. Array(1,2,3,4,5).map(x=>2* x) //完整版
  3. Array(1,2,3,4,5).map(2* _) //简写版
  4. //foreach对传入的每一个元素都进行处理,但是没有返回值
  5. (1 to 9 ).map("@"*_).foreach(println _)
  6. //对比
  7. (1 to 9 ).map("@"*_)
  8. //filter:对传入的每一个元素都进行条件判断,
  9. 如果对元素返回true,则保留该元素,否则过滤掉该元素
  10. (1 to 20 ).filter(_%2==0)
  11. //reduceLeft:从左侧元素开始,进行reduce操作,
  12. 及先对元素1和元素2进行处理,将结果与元素3进行处理,以此类推,
  13. 即为reduce
  14. (1 to 9).reduceLeft(_*_) //等同于1*2*3*4*5*6*7*8*9
  15. (1 to 9).reduceLeft(_+_)
  16. (1 to 9).reduceLeft((x,y)=>x+y)
  17. (1 to 9).reduce((x,y)=>x+y)
  18. //sortWith:对元素进行两两对比,进行排序
  19. Array(3,2,5,9,8,6,1).sortWith(_<_)
  20. //
  21. val list=List (List(1,2),List(3,4,5),List(6,7,8,9))
  22. list.filter(x=>x.length>2)
  23. list.filter(x=>x.contains(2))
  24. .filter(x=>x.length==6 && 7< = <10 &&kw.contains("百度影音"))

函数式编程的集合操作

  • scala的集合体系结构 
    集合体系主要包括:Iterable,Seq,Set,Map 
    其中Iterable是所有集合trait的根trait 
    scala的集合是分成可变集合和不可变集合 
    可变集合是指元素可以动态修改(scala.collection.mutable) 
    不可变集合的元素在初始化后就无法修改了(scala.collection.immutable) 
    Seq中包含了Range,ArrayBuffer,List等子trait 
    Rang表示一个序列,通常可以使用“1 to 10”这种语法产生一个Range 
    ArrayBuffer类似java中的ArrayList
  • list 
    List表示一个不可变的列表 
    List有head,tail, 
    head表示List的第一个元素 
    tail代表第一个元素后的所有元素list.head,list.tail 
    List有特殊的操作符::,用于将两个List合并成一个List 
    如果一个List只有一个元素,那么它的head就是这个元素,tail就是Nil 
    Nil是一个空的List,定义为List[Nothing]
  1. //创建List
  2. val list=List(1,2,3,4)
  3. val list1=0::list
  4. val list2=list:::list1
  5. val list3=list::list1 //list整体作为一个元素
  6. //案例
  7. def decorator(list:List[Int],prefix:String){
  8. if(list!=Nil){
  9. println(prefix+list.head)
  10. println(list)
  11. decorator(list.tail,prefix)
  12. }
  13. }
  14. val list=List(6,7,8,9,10)
  15. decorator(list,"@@")
  • LinkedList 
    代表一个可变的列表,使用elem可以引用其头部,使用next可以引用其尾部
  1. val list=scala.collection.mutable.LinkedList(6,7,8,9,10)
  2. list.elem
  3. list.next
  4. //
  5. val list=scala.collection.mutable.LinkedList(6,7,8,9,10)
  6. var currentList=list
  7. while(currentList!=Nil){
  8. currentList.elem=currentList.elem*2
  9. currentList=currentList.next
  10. }
  11. //小技巧
  12. val tuple=("Tom",(20,90))
  13. tuple._1
  14. tuple._2
  15. tuple._2._2
  • Set 
    代表一个没有重复元素的集合 
    set不保证插入顺序,也就是说Set是乱序的
  1. //无序性
  2. val s = new scala.collection.mutable.HashSet[Int]();s+=1;s+=2;s+=5
  3. //LinkHashSet会使用链表维护插入顺序
  4. val s1 = new scala.collection.mutable.LinkedHashSet[Int]();s+=1;s+=2;s+=5
  5. //SortedSet会根据key进行排序
  6. val s2 =scala.collection.mutable.SortedSet("orange","apple","banana")
  • 集合的函数时编程
  1. //为每一个元素添加前缀
  2. List("Tom","sam").map("name is"+_)
  3. //将多行句子拆分成单词
  4. List("hello world","you me").flatMap(_.split(" "))
  5. //打印每一个单词
  6. List("i","have","a","boy").foreach(println(_))
  7. //将连个list进行关联
  8. List("Leo","jack").zip(List(100,90))
  • 函数式编程案例:统计多个文本内的单词总数
  1. val lines=scala.io.Source.fromFile("C://Users//Lyuc//Desktop//asdasd.txt").mkString
  2. val linesss=List(lines)
  3. linesss.flatMap(_.split("\t")).map((_,1)).map(_._2).reduceLeft(_+_)
  4. //完整版
  5. lines.flatMap(x=>split("\t")).map(x=>x,1).map(x=>x._2).reduce(_+_)

模式匹配与类型参数

可以进行模式匹配,类型匹配,对Array,List的元素情况匹配,对case class(样例类)进行匹配,对有值,没值(Option)进行匹配

  • 模式匹配语法基础 
    java的switch case仅能匹配变量的值 
    scala的match case 可以匹配变量的类型,集合的元素,有值,没值 
    如果值为下划线(_):不满足以上所有情况 
    只要满足一个case分支并处理了,就不会继续判断其他case分支 
    语法:变量 match { case 值 => 代码 }
  1. def score(grade:String){
  2. grade match{
  3. case "A"=>println("very good")
  4. case "B"=>println("good")
  5. case "C"=>println("soso")
  6. case "D"=>println("you mother is in the way")
  7. }
  8. }
  • 在模式匹配中使用if守卫 
    在case后的条件判断中增加一个if守卫,进行双重过滤
  1. case _if name=="leo"=>println("no zuo no die")
  • 在模式匹配中进行变量赋值 
    可以将默认情况(_)替换为一个变量名,在模式匹配下会将要匹配的值,赋值给这个变量,从而可以在后面处理语句中使用要匹配的值
  1. def score(name:String,grade:String){
  2. grade match{
  3. case "A"=>println(name+"very good")
  4. case "B"=>println(name+"good")
  5. case "C"=>println(name+"soso")
  6. case "D"=>println(name+"you mother is in the way")
  7. case _grade if name=="leo" => println(name+"no zuo no die"+_grade)
  8. case _grade =>println("you must work hard"+_grade)
  9. }
  10. }
  • 对类型进行模式匹配 
    可以直接匹配类型 
    语法格式:case 变量:类型 => 代码
  1. import java.io._
  2. def processException(e:Exception){
  3. e match{
  4. case e1:IllegalArgumentException => println("you have illegal arguments!"+e1)
  5. case e2:FileNotFoundException => println("cannot find the file you need or write!"+e2)
  6. case e3:IOException => println("you got an error while you were doing IO"+e3)
  7. case _:Exception => println("cannot know which exception you you have!")
  8. }
  9. }
  • 对Array和List的元素进行模式匹配 
    对Array进行模式匹配,可以匹配带有指定元素的数组,带有指定个数的元素,以某个元素开头的数组 
    对List进行模式匹配,与Array相似,但是要使用::操作符
  1. //对Array进行模式匹配
  2. def greeting(arr:Array[String]){
  3. arr match{
  4. case Array("Leo") => println("hello,leo")
  5. case Array(gril1,gril2,gril3) => println("hello"+gril1+"and"+gril2+"and"+gril3)
  6. case Array("Leo",_*) => println("=====hello,leo=====")
  7. case _=> println("who are you ?")
  8. }
  9. }
  10. val arr1=Array("Leo")
  11. val arr2=Array("Amy","jen","jeny")
  12. val arr3=Array("Leo","sam")
  13. val arr4=Array("asdasd")
  14. greeting(arr1)
  15. //对List的元素进行模式匹配
  16. //
  17. def greeting(list:List[String]){
  18. list match{
  19. case "Leo"::Nil => println("hello,leo")
  20. case gril1::gril2::gril3::Nil => println("hello"+gril1+"and"+gril2+"and"+gril3)
  21. case "Leo"::tail => println("=====hello,leo=====")
  22. case _=> println("who are you ?")
  23. }
  24. }
  25. val list1=List("Leo")
  26. val list2=List("Amy","jen","jeny")
  27. val list3=List("Leo","sam")
  28. val list4=List("asdasd")
  29. greeting(list1)
  • case class(样例类)与模式匹配 
    样例类,使用case class声明 
    只定义field,并由scala直通提供getter和setter方法,没有method 
    case classde 主构造函数接受的参数通常不需要使用val,var修饰,scala会自动使用val使用 
    scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接受主构造函数中相同的参数,并放回case class对象
  1. class person
  2. case class Teacher(name:String,subject:String) extends person
  3. case class Student(name:String,classroom:String) extends person
  4. def judgeldentify(p:person){
  5. p match{
  6. case Teacher(name,subject) => println("Teacher,name is"+ name+",subject is"+subject)
  7. case Student(name,classroom) => println("studnet,name is"+ name+",classroom is"+classroom)
  8. case _ => println("what the fuck! who you are!")
  9. }
  10. }
  11. val p1 = new Student("tom","classrom1")
  12. val p2 = new Teacher("sam","BD")
  13. judgeldentify(p1)
  14. judgeldentify(p2)
  • Option与模式匹配 
    scala中有一种特殊的类型——Option 
    Option有两种值,一种是Some(表示有值),一种是None(表示没有值) 
    Option通常用在匹配模式中,用于判断某个变量是否有值
  1. val grades =Map("Leo"->"A","jake"->"B","sam"->"C")
  2. def getGrade(name:String){
  3. val grade=grades.get(name)
  4. grade match{
  5. case Some(grade)=>println("your grade is "+ grade)
  6. case None=>println("sorry")
  7. }
  8. }

类型参数

*泛型类

  1. class student[T](val localid:T){
  2. def getSchool(hukouid:T)="S-"+hukouid+"-"+localid
  3. }
  4. val leo = new student[Int](111)
  5. val jack = new student(1)
  6. leo.getSchool(123)
  7. jack.getSchool(456)
  8. println(jack.getSchool(456))
  • 泛型函数
  1. def getCard[T](content:T)={
  2. if(content.isInstanceOf[Int])"card:001"+content
  3. else if (content.isInstanceOf[String]) "this is you card"+content
  4. else "card:"+content
  5. }
  6. getCard[String]("hello world")
  • 协变和逆变
  1. class Master
  2. class Professional extends Master
  3. class Card[+T](val name:String){
  4. def enterMeet(card:Card[Master]){
  5. println(name+"======"+"welcome to have this meeting!")
  6. }
  7. }
  8. val aa=new Card[Master]("tom")
  9. val bb= new Card[Professional]("jack")
  10. aa.enterMeet(aa)
  11. bb.enterMeet(bb)
  12. aa.enterMeet(bb)
  13. bb.enterMeet(aa)
  14. //逆变
  15. class Master
  16. class Professional extends Master
  17. classCard[-T](val name:String){
  18. def enterMeet(card:Card[Professional]){
  19. println(name+"--------"+"welcome to have this meeting!")
  20. }
  21. }
  22. val aa=new Card[Master]("tom")
  23. val bb= new Card[Professional]("jack")

隐式转换和隐式参数

  • 隐式函数 
    隐式转换函数:implicit conversion function
  1. class Num{ }
  2. class RichNum(num:Num){
  3. def rich{
  4. print("this is a richInt")
  5. }
  6. }
  7. object ImplicitDemo{
  8. implicit def num2richNum(num:Num)=new richNum(num)
  9. def main(args:Array[String]):Unit={
  10. val num= new Num()
  11. num.rich()
  12. }
  13. }

隐式函数

  1. object Int2StringTest{
  2. implicit def int2String(i:Int)=i.toString()
  3. def main(args:Array[String]):Unit={
  4. print(5.length())
  5. }
  6. }

隐式导入函数 
import ImplicitPro.Int2StringTest._将Int2String内部的额成员导入到相应的作用域内,否则无法调用隐式函数

  1. import ImplicitPro.Int2StringTest._
  2. object ImplicitTest{
  3. def main(args:Array[String]):Unit={
  4. println(4.length())
  5. }
  6. }
  • 隐式转换
  1. class SpecialPerson(val name:String)
  2. class Student(val name:String)
  3. class Older(vla name:String)
  4. implicit def object2SpecialPerson(obj:Object):SpecialPerson={
  5. if(obj.getClass ==classOf[Student]){val stu =obj.asInstanceOf[Student];new SpecialPerson(stu,name)}
  6. else if (obj.getclass==classOf[Older]){ val older = obj.asInstanceOf[Older];new SpecialPerson(older.name)}
  7. else Nil
  8. }
  9. var ticketNumber=0
  10. def buySpecialTicket(p:SpericaPerson)={
  11. ticketNumber+=1
  12. "T-"+ticketNumber
  13. }
  14. def mian(args:Array[String]):Unit={
  15. val stu = new Studnet("asdasd")
  16. val Older = new Older("qweqwe")
  17. buySpecialTicket(stu)
  18. buySpecialTicket(old)
  19. }
  • 使用隐式转换加强现有类型
  • 隐式参数
  1. class signPen{
  2. def write(context:String)=println(context)
  3. }
  4. implicit val signPen = new SignPen
  5. def SignForExam()

闭包

函数在比变量不处于有效的作用域的时,依然能进行访问,称为闭包

  1. def aa(msg:String)=(name:String)=>println(msg+","+name)
  2. val bb=aa("hello")
  3. val cc=aa("hi")

Currying(柯里化函数)

将原来接受两个参数的一个函数,转化为两个函数,第一个函数接受原来的第一个参数。然后返回接受原来接受第二个参数的第二个函数 
在函数的调用过程中就变味了两个函数连续调用的形式

  1. def sum(a:Intb:Int)=a+b
  2. sum(1,1)
  3. def sum1(a:Int),(b:Int)=a+b
  4. sum1(1)(1)

Actor

类似java中的多线程 
scala的Actor尽可能的避免锁和共享状态,还可以避免死锁等一系列多线程编程问题 
Spark使用的分布式多线程框架是Akka,Akka也实现了类似Scala Actor模型,核心概念也是Actor

  • Actor 的创建,启动和消息的收发 
    scala提供Actor trait来让我们方便的今次那个actor多线程编程 
    只要重写act方法即可 
    使用start()方法启动actor 
    使用!向actor发送消息 
    actor内部使用receive和模式匹配接收消息
  1. import scala.actors.Actor
  2. class HelloActor extends Actor{
  3. def act(){
  4. while (true){
  5. receive{
  6. case name:String=>println("hello"+" "+name)
  7. }
  8. }
  9. }
  10. }
  11. object Actoremo {
  12. def main(args: Array[String]): Unit = {
  13. val helloActor=new HelloActor
  14. helloActor.start()
  15. helloActor!"leo"
  16. }
  17. }
  • 收发case class类型的消息 
    scala中一个actor可以给其他actor直接发送消息,使用“actor!消息”的语法模式 
    通常使用样例类,即case class 来作为消息惊醒发送,然后在actor接收消息,可以使用模式匹配功能来进行不同消息的处理
  1. case class Login(username:String,password:String)
  2. case class Register(username:String,password:String)
  3. class UserManageActor extends Actor{
  4. def act(){
  5. while(true){
  6. receive{
  7. case Login(username,password)=>println("login username is"+username+", password is"+password)
  8. case Register(username,password)=>println("register username is"+username+", password is"+password)
  9. }
  10. }
  11. }
  12. }
  13. val userManageActor = new UserManageActor
  14. userManageActor.start()
  15. userManageActor!Register("leo","123123");
  16. userManageActor!Loginr("leo","123123");
  • Actor之间互相收发消息 
    如果两个Actor之间要是互相收发消息,有一个scala向另一个actor发行消息,同时带上自己的引用,其他actor收到自己的消息时,直接通过发送消息的actor的引用,可以回复消息
  1. import scala.actors.Actor
  2. case class Message(content:String,sender:Actor)
  3. class LeoTelephoneActor extends Actor{
  4. def act(){
  5. while(true){
  6. receive{
  7. case Message(content,sender)=>{
  8. println("leo telephone:" +context );sender!"i am leo, please call me after 10 hour later"
  9. }
  10. }
  11. }
  12. }
  13. }
  14. class jackTelephoneActor(val leo TelephoneActor:Actor) extends Actor{
  15. def act(){
  16. leo TelephoneActor!Message("hello,leo,I am jack."this)
  17. receive{
  18. case response:String=>println("jack telephone:"+respones)
  19. }
  20. }
  21. }
1 0
原创粉丝点击