一、函数式编程
Scala中的函数式JAVA中完全没有的概念
Scala是一门既面向对象,又面向过程的语言。Scala中的函数可以独立存在,不需要依赖任何类和对象
1、将函数赋值给变量
Scala的语法规定,将函数赋值给变量时,必须在函数后面加上空格和下划线
def sayHello(name: String) { println("Hello, " + name) } val sayHelloFunc = sayHello _ sayHelloFunc("leo")
2、匿名函数可以直接定义函数之后,将函数赋值给某个变量;也可以将直接定义的匿名函数传入其他函数之中
语法规则;
(参数名:参数类型) =>函数体
def sayHello(name: String) { println("Hello, " + name) } val sayHelloFunc = sayHello _ sayHelloFunc("leo")
3、高阶函数接受其他函数作为参数的函数,也被称作高阶函数
val sayHelloFunc = (name: String) => println("Hello, " + name) def greeting(func: (String) => Unit, name: String) { func(name) } greeting(sayHelloFunc, "leo")
高阶函数的另外一个功能是将函数作为返回值
def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name) val greetingFunc = getGreetingFunc("hello") greetingFunc("leo")
高阶函数可以自动推断出参数类型,而不需要写明类型。而且对于只有一个参数的函数,还可以省去其小括号
def greeting(func: (String) => Unit, name: String) { func(name) } greeting((name: String) => println("Hello, " + name), "leo") greeting((name) => println("Hello, " + name), "leo") greeting(name => println("Hello, " + name), "leo")
scala常用的高阶函数
map:对传入的每个元素都进行映射,返回一个处理后的元素
Array(1,2,3,4,5).map(2 * _) 结果为Array(2,4,,6,,8,10) foreach:对传入的每个元素都进行处理,但是没有返回值 (1 to 9).map("*"* _).foreach(println_) filter:对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素 (1 to 20).filter(_ % 2==0) //过滤偶数 reduceLeft:从左侧元素开始,进行reduce操作,ji先对元素1和元素2进行处理,然后将结果与元素3处理,以此类推,即为reduce (1 to 9).reduce(_ * _) //表示1到9的阶乘 sortWith:对元素进行两两相比,进行排序 Array(3,2,4,5,19,10).sortWith(_<_) //升序 Array(3,2,4,5,19,10).sortWith(_>_) // 降序
函数式编程集合操作
scala的集合体系结构主要包括:Iterable、Seq、Set、Map
scala中的集合分成可变和不可变两类集合
Seq下包含了Range、ArrayBuffer、List等子trait。其中Range就代表了一个序列,通常可以使用“1 to 10”这种语法来产生一个Range。ArrayBuffer就类似于Java中的ArrayList。
List
List代表一个不可变的列表,List的创建,val list=List(1,2,3,4)
List有head和tail,head代表List的第一个元素,tail代表第一个元素之后的所有元素,list.head list.tail
List有特殊的::操作符,可用于将head和tail合并成一个List
如股一个List中只有一个元素,那么他的head就是这个元素,他的tail是Nil(空的List)
案例;用递归函数来给List中的每个元素都加上指定前缀,并打印加上前缀的元素
def decorator(list: List[Int], prefix: String) { //list:List[Int] 定义list类型 if (list != Nil) { println(prefix + list.head) decorator(list.tail, prefix) } }
LinkedListLinkedList代表一个可变的列表,使用elem可以引用其头部,使用next可以引用其尾部
val list= scala.collection.mutable.LinkedList(1, 2, 3, 4, 5); list.elem; list.next
案例:使用while循环将LinkedList中的每个元素都乘以2
val list=scala.collection.mutanle.LinkedList(1,2,3,4,5) var currentList=list while(currentList !=Nil){ currentList.elem=currentList.elem *2 courrentList=currentList.next }
案例:使用while循环将LinkedList中,从第一个元素开始,每隔一个元素乘以2
val list = scala.collection.mutable.LinkedList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) var currentList = list var first = true while (currentList != Nil && currentList.next != Nil) { if (first) { currentList.elem = currentList.elem * 2; first = false } currentList = currentList.next.next if (currentList != Nil) currentList.elem = currentList.elem * 2 }
Set
Set代表一个没有重复元素的集合,没有顺序
LinkedHashSet会用一个链表维护插入的顺序
SortedSet会自动根据key来进行排序
val s = new scala.collection.mutable.LinkedHashSet[Int](); s+= 1; s += 2; s += 5
集合的函数式编程
scala的集合类的map,flatmap,reduce,reduceLeft,foreach等这些函数,就是高阶函数,因为可以接受其他函数作为参数
map案例实战:为List中的每个元素都添加一个前缀 List("Leo","Jen","Jack").map("nam is "+ _) flatMap案例实战:将list中的多行句子拆分成单词 List("hello World","SB you").flatMap(_.split(" ")) foreach案例实战:打印List中的每个单词 List("I", "have", "a", "beautiful", "house").foreach(println(_)) zip案例实战:对学生姓名和学生成绩关联 List("Leo", "Jen", "Peter", "Jack").zip(List(100, 90, 75, 83))
函数式编程综合案例:统计多个文本内的单词总数
使用scala的io包将文本文件内的数据读取出来
val lines01 = scala.io.Source.fromFile("C://Users//Administrator//Desktop//test01.txt").mkString val lines02 = scala.io.Source.fromFile("C://Users//Administrator//Desktop//test02.txt").mkString 使用List的伴生对象,将多个文件内的内容创建为一个List val lines = List(lines01, lines02) lines.flatMap(_.split(" ")).map((_,1)).map(_._2).reduce(_ + _)
模式匹配
在模式匹配中使用if守卫
在模式匹配中进行变量赋值
对类型进行模式匹配
对Array和List进行模式匹配
对Array进行模式匹配,分别可以匹配:
带有指定元素的数组、带有指定个数元素的数组、以某元素打头的数组def greeting(arr: Array[String]) { arr match { case Array("Leo") => println("Hi, Leo!") case Array(girl1, girl2, girl3) => println("Hi"+girl1 + " and " + girl2 + " and " + girl3) case Array("Leo", _*) => println("Hello, Leo") case _ => println("hey, who are you?") } }
对List进行模式匹配,与Array类似,但是需要使用List特有的::操作符def greeting(list: List[String]) { list match { case "Leo" :: Nil => println("Hi, Leo!") case girl1 :: girl2 :: girl3 :: Nil => println("Hi " + girl1 + " and " + girl2 + " and " + girl3) case "Leo" :: tail => println("Hi, Leo.") case _ => println("hey, who are you?") } }
case class(样例类)与模式匹配class Person case class Teacher(name: String, subject: String) extends Person case class Student(name: String, classroom: String) extends Person def judgeIdentify(p: Person) { p match { case Teacher(name, subject) => println("Teacher, name is " + name + ", subject is " + subject) case Student(name, classroom) => println("Student, name is " + name + ", classroom is " + classroom) case _ => println("Illegal access, please go out of the school!") } }
case class的 主构造函数接收的参数通常不需要使用var或val修饰,Scala自动就会使用
val修饰
Option与模式匹配
Option有两种值,一种是Some,表示有值,一种是None,表示没有值
案例:成绩查询
val grades = Map("Leo" -> "A", "Jack" -> "B", "Jen" -> "C") def getGrade(name: String) { val grade = grades.get(name) grade match { case Some(grade) => println("your grade is " + grade) case None => println("Sorry!") } }