文章目录
Scala函数式编程高级
package com.atguigu.chapter13
/**
* @Date 2021/4/3 20:21
* @Version 10.21
* @Author DuanChaojie
*/
object PartialFunDemo01 {
def main(args: Array[String]): Unit = {
/**
* 给你一个集合val list = List(1, 2, 3, 4, "abc") ,请完成如下要求:
* 将集合list中的所有数字+1,并返回一个新的集合
* 要求忽略掉 非数字 的元素,即返回的 新的集合 形式为 (2, 3, 4, 5)
*/
/**
* 思路1 filter + map 方式解决
* 虽然可以解决问题,但是麻烦.
*/
val list = List(1, 2, 3, 4, "hello")
/** 方案一:
* val res1 = list.filter(filterFun)
* println("res1 = " + res1)
*
* val res2 = res1.map(anyToInt)
* println("res2 = " + res2)
*
* val res3 = res2.map(funAddOne)
* println("res3 = " + res3)
*/
val res1 = list.filter(filterFun).map(anyToInt).map(funAddOne)
println(res1)
/**
* 解决方案二:使用模式匹配
*/
val res2 = list.map(addOne)
println(res2)
}
def addOne(x: Any): Any = {
x match {
case n: Int => n + 1
case _ =>
}
}
/**
* @param x 输入的类型为Any类型
* @return 输入的x为Int类型才返回true
*/
def filterFun(x: Any): Boolean = {
x.isInstanceOf[Int]
}
/**
* @param n Any类型的参数
* @return 返回Int
*/
def anyToInt(n: Any): Int = {
n.asInstanceOf[Int]
}
/**
* @param n
* @return n + 1
*/
def funAddOne(n: Int): Int = {
n + 1
}
}
1. 偏函数
/**
* @Date 2021/4/3 20:36
* @Version 10.21
* @Author DuanChaojie
*/
object PartialFunDemo02 {
def main(args: Array[String]): Unit = {
//使用偏函数解决
val list = List(1, 2, 3, 4, "hello")
/**
* 定义一个偏函数
* 1. PartialFunction[Any,Int] 表示偏函数接收的参数类型是Any,返回类型是Int
* 2. isDefinedAt(x: Any) 如果返回true ,就会去调用 apply 构建对象实例,如果是false,过滤
* 3. apply 构造器 ,对传入的值 + 1,并返回(新的集合)
*/
val partialFun = new PartialFunction[Any, Int] { // PartialFunction是一个特质
override def isDefinedAt(x: Any): Boolean = {
x.isInstanceOf[Int]
}
override def apply(v1: Any): Int = {
v1.asInstanceOf[Int] + 1
}
}
/**
* 说明:如果是使用偏函数,则不能使用map,应该使用collect
* 说明一下偏函数的执行流程
* 1. 遍历list所有元素
* 2. 然后调用 val element = if(partialFun-isDefinedAt(list单个元素)) {partialFun-apply(list单个元素) }
* 3. 每得到一个 element,放入到新的集合,最后返回
*/
val res = list.collect(partialFun)
// List(2, 3, 4, 5)
println(res)
}
}
偏函数简化形式
声明偏函数,需要重写特质中的方法,有的时候会略显麻烦,而Scala其实提供了简单的方法
/**
* @Date 2021/4/3 20:47
* @Version 10.21
* @Author DuanChaojie
*/
object PartialFunDemo03 {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4, "hello")
/**
* 第一种简写方式:使用case
* @return
*/
def partialFun1: PartialFunction[Any, Int] = {
case i: Int => i + 1
}
val res1 = list.collect(partialFun1)
//res1 = List(2, 3, 4, 5)
println("res1 = " + res1)
/**
* 第二种简写方式:
*/
val res2 = list.collect {
case i: Int => i + 1
}
// res2 = List(2, 3, 4, 5)
println("res2 = " + res2)
}
}
作为参数的函数
函数作为一个变量传入到了另一个函数中,那么该作为参数的函数的类型是:function1
,即:(参数类型) => 返回类型
/**
* @Date 2021/4/3 20:55
* @Version 10.21
* @Author DuanChaojie
*/
object FunParameterDemo01 {
def main(args: Array[String]): Unit = {
def plus(x: Int) = 3 + x
//val res = Array(3,6,9).map(plus(_))
val res = Array(3,6,9).map(plus)
// mkString(seq:String)方法是将原字符串使用特定的字符串seq分割。
// 6,9,12
println(res.mkString(","))
/**
* 在scala中,函数也是有类型,比如plus就是<function1>
*/
println(plus _)
}
}
2. 匿名函数
/**
* @Date 2021/4/3 21:02
* @Version 10.21
* @Author DuanChaojie
*/
object AnonymousFunDemo01 {
def main(args: Array[String]): Unit = {
/**
* 对匿名函数的说明
* 1. 不需要写def函数名
* 2. 不需要写返回类型,使用类型推导
* 3. =变成=>
* 4. 如果有多行,则使用{} 包括
*/
val triple = (x: Double) => {
println("x = " + x)
x * x
}
// triple(3) = 9.0
println("triple(3) = " + triple(3))
}
}
/**
* @Date 2021/4/3 21:41
* @Version 10.21
* @Author DuanChaojie
*/
object AnonymousFunDemo02 {
def main(args: Array[String]): Unit = {
val sum = (n1: Int, n2: Int) => {
n1 + n2
}
// 36
println(sum(21, 15))
// sum函数的类型是:<function2>
println("sum函数的类型是:" + sum)
}
}
3. 高阶函数
/**
* @Date 2021/4/3 21:44
* @Version 10.21
* @Author DuanChaojie
*/
object HigherOrderFunDemo01 {
def main(args: Array[String]): Unit = {
val res = hfun(fun1, fun2, 3.5)
println("res = " + res)
}
/**
* 高阶函数
* @param f1
* @param f2
* @param n
* @return 将n进行以下处理返回:(n+n).toInt
*/
def hfun(f1: Double => Double, f2: Double => Int, n: Double) = {
f2(f1(n))
}
/** 普通函数fun1
* @param x 输入Double类型的值
* @return x + x
*/
def fun1(x: Double): Double = {
x + x
}
/** 普通函数fun2
* @param x 输入Double类型的值
* @return 返回对应的Int
*/
def fun2(x: Double): Int = {
x.toInt
}
}
/**
* @Date 2021/4/3 21:52
* @Version 10.21
* @Author DuanChaojie
*/
object HigherOrderFunDemo02 {
def main(args: Array[String]): Unit = {
/**
* 这里返回的fun1就是minusxy里面的匿名函数:(y: Int) => 3 + y
* 等价于 def fun1 = (y: Int) => 3 + y
* 所以fun1(6)的结果为9
* 也可以一步到位:minusxy(3)(6)
*/
val fun1 = minusxy(3)
// fun1 = <function1>
println("fun1 = " + fun1)
val res = fun1(6)
// res = 9
println("res = " + res)
// minusxy(3)(6) = 9
println("minusxy(3)(6) = " + minusxy(3)(6))
}
def minusxy(x: Int) = {
// 匿名函数
(y: Int) => x + y
}
}
4. 类型推断
/**
* @Date 2021/4/3 22:04
* @Version 10.21
* @Author DuanChaojie
*/
object ParameterInferDemo {
/**
* 参数类型是可以推断时,可以省略参数类型
* 当传入的函数,只有单个参数时,可以省去括号
* 如果变量只在=>右边只出现一次,可以用_来代替
*/
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4)
println(list.map((x: Int) => x + 1)) // List(2, 3, 4, 5)
println(list.map((x) => x + 1)) //List(2, 3, 4, 5)
println(list.map(x => x + 1)) //List(2, 3, 4, 5)
println(list.map(_ + 1)) //List(2, 3, 4, 5)
println(list.reduce(fun1)) // 10
println(list.reduce((n1: Int, n2: Int) => n1 + n2)) //10
println(list.reduce((n1, n2) => n1 + n2)) //10
println(list.reduce(_ + _)) //10
}
def fun1(n1: Int, n2: Int): Int = {
n1 + n2
}
}
5. 闭包
闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)。
通过一个例子了解闭包:
object Demo {
def main(args: Array[String]): Unit = {
val fun1 = minusxy(3)
val res1 = fun1(6)
val res2 = fun1(9)
}
def minusxy(x: Int) = {
// 匿名函数
(y: Int) => x + y
}
}
闭包的最佳实践
/**
* @Date 2021/4/3 22:13
* @Version 10.21
* @Author DuanChaojie
*/
object ClosureDemo01 {
def main(args: Array[String]): Unit = {
val fun = makeSuffix(".png")
// dog.png
println(fun("dog.png"))
// cat.png
println(fun("cat"))
}
/**
* @param suffix 传入
* @return
*/
def makeSuffix(suffix: String) = {
// 返回一个匿名函数,会使用到suffix
(filename: String) => {
if (filename.endsWith(suffix)) {
filename
} else {
filename + suffix
}
}
}
}
6. 函数柯里化(curry)
函数柯里化快速入门
/**
* @Date 2021/4/3 22:20
* @Version 10.21
* @Author DuanChaojie
*/
object CurryDemo01 {
def main(args: Array[String]): Unit = {
// 使用常规的方式完成
def curry1(x: Int, y: Int) = x * y
println(curry1(10, 10))
// 使用闭包的方式完成
def curry2(x: Int) = (y: Int) => x * y
println(curry2(10)(10))
// 使用函数柯里化完成
def curry3(x: Int)(y: Int) = x * y
println(curry3(10)(10))
}
}
函数柯里化最佳实践
/**
* @Date 2021/4/3 22:23
* @Version 10.21
* @Author DuanChaojie
*/
object CurryDemo02 {
def main(args: Array[String]): Unit = {
val str = "ddaimm"
// false
println(str.compareStr("HELLO")(fun))
// true
println(str.compareStr("ddaimm")(_.equals(_)))
}
/**
* 可以接收两个字符串,比较是否相等
*/
def fun(str1: String, str2: String): Boolean = {
str1.equals(str2)
}
/**
* 隐式类
*/
implicit class compare(str1: String) {
/**
* 体现了将比较字符串的事情,分解成两个任务完成
* 1. compareStr 转换大小写
* 2. fun函数完成比较任务
*/
def compareStr(str2: String)(fun: (String, String) => Boolean): Boolean = {
fun(str2.toUpperCase(), str1.toUpperCase())
}
}
}
7. 控制抽象
var n = 10
breakable {
while (n <= 20) {
n += 1
if (n == 18) {
break()
}
}
}
/**
* @Date 2021/4/3 22:37
* @Version 10.21
* @Author DuanChaojie
*/
object AbstractControlDemo01 {
def main(args: Array[String]): Unit = {
/**
* myRunInThread 就是一个抽象控制
* 是没有输入, 也没有输出的函数 f1: () => Unit
*/
def myRunInThread(f1: () => Unit) = {
new Thread {
override def run(): Unit = {
f1() //只写了 f1
}
}.start()
}
myRunInThread { () => {
println("mm干活咯!5秒完成...")
Thread.sleep(5000)
println("mm干完咯!")
}
}
//简写形式
def myRunInThread2(f1: => Unit) = {
new Thread {
override def run(): Unit = {
f1 //只写了 f1
}
}.start()
}
// 对于没有输入,也没有返回值函数,可以简写成如下形式
myRunInThread2 {
println("dd干活咯!5秒完成...")
Thread.sleep(5000)
println("dd干完咯!")
}
}
}
/**
* @Date 2021/4/3 22:44
* @Version 10.21
* @Author DuanChaojie
*/
object AbstractControlDemo02 {
def main(args: Array[String]): Unit = {
var x = 10
until(x == 0) {
x -= 1
println("x=" + x)
}
}
/** 说明
* 1 函数名为 until , 实现了类似 while循环的效果
* 2. condition: => Boolean 是后一个没有输入值,返回Boolean类型函数
* 3. block: => Unit 没有输入值,也没有返回值的韩
*/
def until(condition: => Boolean)(block: => Unit): Unit = {
//类似while循环,递归
if (!condition) {
block // x= 9 ,x = 8 x =7 ....
until(condition)(block)
}
}
}