您的位置:首页 > 编程语言

学习笔记—scala高级编程

2017-03-18 23:11 351 查看


函数式编程

scala 中函数可以独立存在,不需要依赖任何类和对象
将函数赋值给变量

使用def定义方法和函数

函数,方法的区别是出现的位置不同,在类里面是方法 ,在类外是函数

//将函数赋值给变量时,必须在函数后加上空格和下划线

def say(name:String) {println("hello"+name)}

val sayFunc=say _

sayFunc("leo")

[/code]

匿名函数

没有名字的函数称为匿名函数

可以直接定义函数后将函数赋值给某个变量,也可以将匿名函数传入其它函数中

定义匿名函数的语法规则:(参数名:参数类型)=>函数体

//匿名函数

val aa=(name:String)=>println("hello"+name)

[/code]

高阶函数

接受其他函数作为参数的函数称为高阶函数

可以直接将某个函数作为参数传入其他函数
将函数作为返回值

//将函数作为参数

val say=(name:String) => println("hello"+" "+name)

def greeting(func:(String) => Unit,name:String){func(name)}

greeting(say,"Tom")

//将函数作为返回值

def getGreetingFunc(msg:String)=(name:String)=>println(msg+","+name )

val greetingFunc=getGreetingFunc("hello")

greetingFunc("leo")

[/code]

Map和faltMap的区别
lines.map(x=>x.split(" ")).collection


//faltMap:faltten Map ,先执行map,后执行flatten(扁平化)

lines.flatmap(x=>x.split(" ")).collection


//

line.map(x=>x.split(" ")(2) )     //取新形成数组的索引为2 的值

lines.first      //只取第一条数据

[/code]

高阶函数的类型推断

高阶函数可以自动推断参数类型,不需要写明类型

如果函数只有一个参数,可以省略小括号

greeting ((name:String)=>print("hello"+ " "+name),"tom")

greeting (name=>print("hello"+ " "+name),"tom")

[/code]

scala的常用高阶函数

//map对传入的每一个元素进行映射,返回一个处理后的结果

Array(1,2,3,4,5).map(x=>2* x)      //完整版

Array(1,2,3,4,5).map(2* _)            //简写版


//foreach对传入的每一个元素都进行处理,但是没有返回值

(1 to 9 ).map("@"*_).foreach(println _)

//对比

(1 to 9 ).map("@"*_)

//filter:对传入的每一个元素都进行条件判断,

如果对元素返回true,则保留该元素,否则过滤掉该元素

(1 to 20 ).filter(_%2==0)

//reduceLeft:从左侧元素开始,进行reduce操作,

及先对元素1和元素2进行处理,将结果与元素3进行处理,以此类推,

即为reduce

(1 to 9).reduceLeft(_*_)        //等同于1*2*3*4*5*6*7*8*9

(1 to 9).reduceLeft(_+_)

(1 to 9).reduceLeft((x,y)=>x+y)

(1 to 9).reduce((x,y)=>x+y)

//sortWith:对元素进行两两对比,进行排序

Array(3,2,5,9,8,6,1).sortWith(_<_)


//

val list=List (List(1,2),List(3,4,5),List(6,7,8,9))

list.filter(x=>x.length>2)

list.filter(x=>x.contains(2))


.filter(x=>x.length==6 && 7< = <10 &&kw.contains("百度影音"))

[/code]


函数式编程的集合操作

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]

//创建List

val list=List(1,2,3,4)

val list1=0::list

val list2=list:::list1

val list3=list::list1         //list整体作为一个元素


//案例

def decorator(list:List[Int],prefix:String){

if(list!=Nil){

println(prefix+list.head)

println(list)

decorator(list.tail,prefix)

}

}

val list=List(6,7,8,9,10)

decorator(list,"@@")

[/code]

LinkedList

代表一个可变的列表,使用elem可以引用其头部,使用next可以引用其尾部

val list=scala.collection.mutable.LinkedList(6,7,8,9,10)

list.elem

list.next

//

val list=scala.collection.mutable.LinkedList(6,7,8,9,10)

var currentList=list

while(currentList!=Nil){

currentList.elem=currentList.elem*2

currentList=currentList.next

}

//小技巧

val tuple=("Tom",(20,90))

tuple._1

tuple._2

tuple._2._2

[/code]

Set

代表一个没有重复元素的集合

set不保证插入顺序,也就是说Set是乱序的

//无序性

val s = new scala.collection.mutable.HashSet[Int]();s+=1;s+=2;s+=5

//LinkHashSet会使用链表维护插入顺序

val s1 = new scala.collection.mutable.LinkedHashSet[Int]();s+=1;s+=2;s+=5

//SortedSet会根据key进行排序

val s2 =scala.collection.mutable.SortedSet("orange","apple","banana")

[/code]

集合的函数时编程

//为每一个元素添加前缀

List("Tom","sam").map("name is"+_)

//将多行句子拆分成单词

List("hello world","you me").flatMap(_.split(" "))

//打印每一个单词

List("i","have","a","boy").foreach(println(_))

//将连个list进行关联

List("Leo","jack").zip(List(100,90))

[/code]

函数式编程案例:统计多个文本内的单词总数

val lines=scala.io.Source.fromFile("C://Users//Lyuc//Desktop//asdasd.txt").mkString

val linesss=List(lines)

linesss.flatMap(_.split("\t")).map((_,1)).map(_._2).reduceLeft(_+_)


//完整版

lines.flatMap(x=>split("\t")).map(x=>x,1).map(x=>x._2).reduce(_+_)


[/code]


模式匹配与类型参数

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

模式匹配语法基础

java的switch case仅能匹配变量的值

scala的match case 可以匹配变量的类型,集合的元素,有值,没值

如果值为下划线(_):不满足以上所有情况

只要满足一个case分支并处理了,就不会继续判断其他case分支

语法:变量 match { case 值 => 代码 }

def score(grade:String){

grade match{

case "A"=>println("very good")

case "B"=>println("good")

case "C"=>println("soso")

case "D"=>println("you mother is in the way")

}

}

[/code]

在模式匹配中使用if守卫

在case后的条件判断中增加一个if守卫,进行双重过滤

case _if name=="leo"=>println("no zuo no die")

[/code]

在模式匹配中进行变量赋值

可以将默认情况(_)替换为一个变量名,在模式匹配下会将要匹配的值,赋值给这个变量,从而可以在后面处理语句中使用要匹配的值

def score(name:String,grade:String){

grade match{

case "A"=>println(name+"very good")

case "B"=>println(name+"good")

case "C"=>println(name+"soso")

case "D"=>println(name+"you mother is in the way")

case _grade if name=="leo" => println(name+"no zuo no die"+_grade)

case _grade =>println("you must work hard"+_grade)

}

}

[/code]

对类型进行模式匹配

可以直接匹配类型

语法格式:case 变量:类型 => 代码

import java.io._

def processException(e:Exception){

e match{

case e1:IllegalArgumentException => println("you have illegal arguments!"+e1)

case e2:FileNotFoundException => println("cannot find the file you need or write!"+e2)

case e3:IOException => println("you got an error while you were doing IO"+e3)

case _:Exception => println("cannot know which exception you you have!")

}

}

[/code]

对Array和List的元素进行模式匹配

对Array进行模式匹配,可以匹配带有指定元素的数组,带有指定个数的元素,以某个元素开头的数组

对List进行模式匹配,与Array相似,但是要使用::操作符

//对Array进行模式匹配


def greeting(arr:Array[String]){

arr match{

case Array("Leo") => println("hello,leo")

case Array(gril1,gril2,gril3) => println("hello"+gril1+"and"+gril2+"and"+gril3)

case Array("Leo",_*) => println("=====hello,leo=====")

case _=> println("who are you ?")

}

}


val arr1=Array("Leo")

val arr2=Array("Amy","jen","jeny")

val arr3=Array("Leo","sam")

val arr4=Array("asdasd")

greeting(arr1)



//对List的元素进行模式匹配

//

def greeting(list:List[String]){

list match{

case "Leo"::Nil => println("hello,leo")

case gril1::gril2::gril3::Nil => println("hello"+gril1+"and"+gril2+"and"+gril3)

case "Leo"::tail => println("=====hello,leo=====")

case _=> println("who are you ?")

}

}


val list1=List("Leo")

val list2=List("Amy","jen","jeny")

val list3=List("Leo","sam")

val list4=List("asdasd")

greeting(list1)

[/code]

case class(样例类)与模式匹配

样例类,使用case class声明

只定义field,并由scala直通提供getter和setter方法,没有method

case classde 主构造函数接受的参数通常不需要使用val,var修饰,scala会自动使用val使用

scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接受主构造函数中相同的参数,并放回case class对象

class person

case class Teacher(name:String,subject:String) extends person

case class Student(name:String,classroom:String) extends person


def judgeldentify(p:person){

p match{

case Teacher(name,subject) => println("Teacher,name is"+ name+",subject is"+subject)

case Student(name,classroom) => println("studnet,name is"+ name+",classroom is"+classroom)

case _ => println("what the fuck! who you are!")

}

}


val p1 = new Student("tom","classrom1")

val p2 = new Teacher("sam","BD")

judgeldentify(p1)

judgeldentify(p2)

[/code]

Option与模式匹配

scala中有一种特殊的类型——Option

Option有两种值,一种是Some(表示有值),一种是None(表示没有值)

Option通常用在匹配模式中,用于判断某个变量是否有值

val grades =Map("Leo"->"A","jake"->"B","sam"->"C")

def getGrade(name:String){

val grade=grades.get(name)

grade match{

case Some(grade)=>println("your grade is "+ grade)

case None=>println("sorry")

}

}

[/code]


类型参数

*泛型类
class student[T](val localid:T){

def getSchool(hukouid:T)="S-"+hukouid+"-"+localid

}

val  leo = new student[Int](111)

val jack = new student(1)


leo.getSchool(123)

jack.getSchool(456)

println(jack.getSchool(456))

[/code]

泛型函数

def getCard[T](content:T)={

if(content.isInstanceOf[Int])"card:001"+content

else if (content.isInstanceOf[String]) "this is you card"+content

else "card:"+content

}


getCard[String]("hello world")

[/code]

协变和逆变

class Master

class Professional extends Master

class Card[+T](val name:String){

def enterMeet(card:Card[Master]){

println(name+"======"+"welcome to have this meeting!")

}

}


val aa=new  Card[Master]("tom")

val bb= new Card[Professional]("jack")


aa.enterMeet(aa)

bb.enterMeet(bb)

aa.enterMeet(bb)

bb.enterMeet(aa)


//逆变

class Master

class Professional extends Master

classCard[-T](val name:String){

def enterMeet(card:Card[Professional]){

println(name+"--------"+"welcome to have this meeting!")

}

}

val aa=new  Card[Master]("tom")

val bb= new Card[Professional]("jack")

[/code]


隐式转换和隐式参数

隐式函数

隐式转换函数:implicit conversion function

class Num{ }

class RichNum(num:Num){

def rich{

print("this is a richInt")

}

}

object ImplicitDemo{

implicit def num2richNum(num:Num)=new richNum(num)

def main(args:Array[String]):Unit={

val num= new Num()

num.rich()

}

}

[/code]

隐式函数
object Int2StringTest{

implicit def int2String(i:Int)=i.toString()

def main(args:Array[String]):Unit={

print(5.length())

}

}

[/code]

隐式导入函数

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

object ImplicitTest{

def main(args:Array[String]):Unit={

println(4.length())

}

}

[/code]

隐式转换

class SpecialPerson(val name:String)

class Student(val name:String)

class Older(vla 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

}


var ticketNumber=0

def buySpecialTicket(p:SpericaPerson)={

ticketNumber+=1

"T-"+ticketNumber

}


def mian(args:Array[String]):Unit={

val stu = new Studnet("asdasd")

val Older = new Older("qweqwe")

buySpecialTicket(stu)

buySpecialTicket(old)

}

[/code]

使用隐式转换加强现有类型
隐式参数

class  signPen{

def write(context:String)=println(context)

}

implicit val signPen = new SignPen

def SignForExam()

[/code]


闭包

函数在比变量不处于有效的作用域的时,依然能进行访问,称为闭包
def aa(msg:String)=(name:String)=>println(msg+","+name)

val bb=aa("hello")

val cc=aa("hi")

[/code]


Currying(柯里化函数)

将原来接受两个参数的一个函数,转化为两个函数,第一个函数接受原来的第一个参数。然后返回接受原来接受第二个参数的第二个函数

在函数的调用过程中就变味了两个函数连续调用的形式
def sum(a:Int,b:Int)=a+b

sum(1,1)


def sum1(a:Int),(b:Int)=a+b

sum1(1)(1)

[/code]


Actor

类似java中的多线程

scala的Actor尽可能的避免锁和共享状态,还可以避免死锁等一系列多线程编程问题

Spark使用的分布式多线程框架是Akka,Akka也实现了类似Scala Actor模型,核心概念也是Actor

Actor 的创建,启动和消息的收发

scala提供Actor trait来让我们方便的今次那个actor多线程编程

只要重写act方法即可

使用start()方法启动actor

使用!向actor发送消息

actor内部使用receive和模式匹配接收消息

import scala.actors.Actor

class HelloActor extends Actor{

def act(){

while (true){

receive{

case name:String=>println("hello"+"  "+name)

}

}

}


}

object Actoremo {

def main(args: Array[String]): Unit = {

val helloActor=new HelloActor

helloActor.start()

helloActor!"leo"

}

}

[/code]

收发case class类型的消息

scala中一个actor可以给其他actor直接发送消息,使用“actor!消息”的语法模式

通常使用样例类,即case class 来作为消息惊醒发送,然后在actor接收消息,可以使用模式匹配功能来进行不同消息的处理

case class Login(username:String,password:String)

case class Register(username:String,password:String)

class UserManageActor extends Actor{

def act(){

while(true){

receive{

case Login(username,password)=>println("login username is"+username+", password is"+password)

case Register(username,password)=>println("register username is"+username+", password is"+password)

}

}

}

}


val userManageActor = new UserManageActor

userManageActor.start()

userManageActor!Register("leo","123123");

userManageActor!Loginr("leo","123123");

[/code]

Actor之间互相收发消息

如果两个Actor之间要是互相收发消息,有一个scala向另一个actor发行消息,同时带上自己的引用,其他actor收到自己的消息时,直接通过发送消息的actor的引用,可以回复消息

import scala.actors.Actor

case class Message(content:String,sender:Actor)

class LeoTelephoneActor extends Actor{

def act(){

while(true){

receive{

case Message(content,sender)=>{

println("leo telephone:" +context );sender!"i am leo, please call me after 10 hour later"

}

}

}

}

}


class jackTelephoneActor(val leo TelephoneActor:Actor) extends Actor{

def act(){


leo TelephoneActor!Message("hello,leo,I am jack."this)

receive{

case response:String=>println("jack telephone:"+respones)

}

}

}

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息