一、什么是函数式编程
- Scala是一门既面向对象,又面向过程的语言
- 在Scala中,函数与类、对象一样,都是一等公民。Java中,函数不能脱离类存在的
- Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量
- Scala的语法规定:将函数赋值给变量时,必须在函数后面加上空格和下划线
1.1、匿名函数
- Scala中的函数也可以不需要命名,这种函数称为匿名函数
- 匿名函数的语法格式:(参数名:参数类型)=>函数体
- 可以将匿名函数直接赋值给某个变量
//匿名函数
val sayHelloFunc = (name: String) => println("Hello " + name)
1.2、高阶函数
- 由于函数是一等公民,所以我们可以直接将某个函数作为参数传入其他函数
- 接收其他函数作为当前函数的参数,当前函数也被称为高阶函数
- 高阶函数可以自动推断出它里面函数的参数类型,对于只有一个参数的函数,还可以省去小括号
package com.strivelearn.scala.scalafunction
/**
* @author strivelearn
* @version MyFunction.java, 2022年11月13日
*/
class MyFunction {
//匿名函数
val sayHelloFunc = (name: String) => println("Hello " + name)
//高阶函数
def sayHello(func: (String) => Unit, name: String): Unit = {
func(name)
}
}
object MyFunction {
def main(args: Array[String]): Unit = {
val function = new MyFunction()
function.sayHello(function.sayHelloFunc, "World")
}
}
1.3、常用的高阶函数
-
map
对传入的每个元素都进行处理,最终会返回一个元素
-
flatMap
对传入的每个元素都进行处理,返回一个或者多个元素
-
foreach
对传入的每个元素都进行处理,没有返回值
-
filter
对传入的每个元素都进行一个条件判断,做过滤
-
reduceLeft
类似hadoop的reduce,进行聚合,从左侧开始进行聚合操作
二、词频统计
package com.strivelearn.scala.highorder
/**
* @author strivelearn
* @version WordCount.java, 2022年11月13日
*/
object WordCount {
def main(args: Array[String]): Unit = {
val str = "hello you hello me"
val str1 = "hello hehe hello haha"
val list = List(str, str1)
//map简写
list.flatMap(_.split(" ")).map(word => (word, 1))
//map 这边定义一个元祖
val i = list.flatMap(_.split(" ")).map((_, 1)).map(tup => tup._2).reduceLeft(_ + _)
println(i)
}
}
三、Scala的高级特性
3.1、模式匹配
- Scala没有Java种的switch case语法,但是,Scala提供了更加强大的match case语法,即模式匹配
- Java的switch case仅能匹配变量的值,Scala的match case可以匹配各种情况,比如:变量的类型,集合的元素,有值没有值
- 语法格式:变量
match{case 值=>代码} - 在match case只要有一个分支满足条件,就不会走其他分支,与Java不一样,Java需要使用break语法
package com.strivelearn.scala.highorder
import java.io.{FileNotFoundException, IOException}
/**
* @author strivelearn
* @version Demo.java, 2022年11月13日
*/
object Demo {
def test(day: Int): Unit = {
day match {
case 1 => println("星期一")
case 2 => println("星期二")
case 3 => println("星期三")
case 4 => println("星期四")
case 5 => println("星期五")
case 6 => println("星期六")
case 7 => println("星期日")
case _ => println("none")
}
}
def processException(e: Exception): Unit = {
e match {
case e1: FileNotFoundException => println("FileNotFoundException")
case e2: IOException => println("IOException")
case _: Exception => println
}
}
def main(args: Array[String]): Unit = {
test(1)
processException(new IOException)
}
}
3.2、case class
- case class称为样例类,类似于Java中的JavaBeaen,只定义field。Scala自动提供getter和setter方法,没有method
- case class的主构造函数接收的参数通常不需要使用
var或者val修饰,Scala会自动使用val修饰 - Scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接收主构造函数中相同的参数并返回case class对象
package com.strivelearn.scala.caseclass
/**
* @author strivelearn
* @version Person.java, 2022年11月13日
*/
class Person {
}
case class Student(name: String, cla: String) extends Person
case class Teacher(name: String, sub: String) extends Person
package com.strivelearn.scala.caseclass
/**
* @author strivelearn
* @version Test.java, 2022年11月13日
*/
object Test {
def check(p: Person): Unit = {
p match {
case Teacher(name, sub) => println(name + " " + sub)
case Student(name, cla) => println(name + " " + cla)
case _ => println("none")
}
}
def main(args: Array[String]): Unit = {
check(new Student("zhangsan", "class1"))
}
}
3.3、Option与模式匹配
- Option有两种值,Some->表示有值,None->表示没值
- Option通常会用于模式匹配中,用于判断某个变量是有值还是没值,这比null更加简洁明了
def main(args: Array[String]): Unit = {
val stringToInt = Map("a" -> 1, "b" -> 2)
//直接报错。java.util.NoSuchElementException: key not found: a1
//val i = stringToInt("a1")
val maybeInt = stringToInt.get("a1")
//输出None
println(maybeInt)
}
def getAge(key: String, map: Map[String, Int]): Unit = {
val age = map.get(key)
age match {
case Some(age) => println("age: " + age)
case None => println("none")
}
}
3.4、隐式转换
- Scala的隐式转换,允许手动指定将某种类型的对象转换为其它类型的对象
- Scala的隐式转换,最核心的就是定义隐式转换函数,即
implicit conversion function - 隐式转换函数与普通函数唯一的语法区别是要以
implicit开头而且最好要定义函数返回类型
Scala默认会自动使用两种隐式转换
- 源类型:或者目标类型的伴生对象里面的隐式转换函数
- 当前程序作用域内可以用唯一标识符表示的隐式转换函数
- 如果隐式转换函数不在上述两种情况下,那么就必须手动使用import语法引入某个包下的隐式转换函数
- 建议:仅仅在需要进行隐式转换的地方
隐式转换案例:让狗会飞
package com.strivelearn.scala.test
import scala.language.implicitConversions
/**
* @author strivelearn
* @version Dog.java, 2022年11月13日
*/
class Dog(val name: String) {
implicit def obj2Bird(obj: Object): Bird = {
if (obj.getClass == classOf[Dog]) {
val dog = obj.asInstanceOf[Dog]
new Bird(dog.name)
} else null
}
}
object DogTest{
def main(args: Array[String]): Unit = {
val dog = new Dog("旺财")
val bird = dog.obj2Bird(dog)
bird.fly()
}
}
package com.strivelearn.scala.test
/**
* @author strivelearn
* @version Bird.java, 2022年11月13日
*/
class Bird(val name: String) {
def fly() {
println(name + "can fly")
}
}
旺财can fly