13.1 偏函数(partial function)
13.1.1 需求 -> 思考
一个集合val list = List(1,2,3,4,"abc"),完成如下要求
1) 将集合list中的所有数字+1,并返回一个新的集合
2) 要求忽略掉非数字的元素,即返回的新的集合形式为(2,3,4,5)
13.1.2 解决方式-filter+map返回新的集合,引出偏函数
13.1.3 解决方式-模式匹配
object boke_demo01 { def main(args: Array[String]): Unit = { //思路1 filter + map 方式解决 //虽然可以解决问题,但是麻烦. val list = List(1, 2, 3, 4, "hello") // 先过滤,再map println(list.filter(f1).map(f3).map(f2)) //思路2-模式匹配 //小结:虽然使用模式匹配比较简单,但是不够完美 val list2 = list.map(addOne2) println("list2=" + list2) } //模式匹配 def addOne2(i: Any): Any = { i match { case x: Int => x + 1 case _ => } } def f1(n: Any): Boolean = { n.isInstanceOf[Int] } def f2(n: Int): Int = { n + 1 } //将Any->Int [map] def f3(n: Any): Int = { n.asInstanceOf[Int] } }
13.1.4 偏函数快速入门
-使用偏函数解决前面的问题
-案例演示
object boke_demo01 { 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] { override def isDefinedAt(x: Any) = { println("x=" + x) x.isInstanceOf[Int] } override def apply(v1: Any) = { println("v1=" + v1) v1.asInstanceOf[Int] + 1 } } //使用偏函数 //说明:如果是使用偏函数,则不能使用map,应该使用collect //说明一下偏函数的执行流程 //1. 遍历list所有元素 //2. 然后调用 val element = if(partialFun-isDefinedAt(list单个元素)) {partialFun-apply(list单个元素) } //3. 每得到一个 element,放入到新的集合,最后返回 val list2 = list.collect(partialFun) println("list2" + list2) } }
13.1.5 偏函数的小结
1) 使用构建特质的实现类(使用的方式是PartialFunction的匿名子类)
2) PartialFunction是个特质
3) 构建偏函数时,参数形式[Any,Int]是泛型,第一个表示参数类型,第二个表示返回参数
4) 当使用偏函数时,会遍历集合的所有元素,编译器执行流程时先执行isDefinedAt(),如果为true,就会执行apply,构建一个新的对象返回
5) 执行isDefinedAt()为false就过滤掉这个元素,即不构建新的Int对象
6) map函数不支持偏函数,因为map底层的机制就是所有循环遍历,无法过滤处理原来集合的元素
7) collect函数支持偏函数
13.1.6 偏函数的简写形式
object boke_demo01 { def main(args: Array[String]): Unit = { //可以将前面的案例的偏函数简写 def partialFun: PartialFunction[Any, Int] = { //简写成case 语句 case i: Int => i + 1 case j: Double => (j * 2).toInt } val list = List(1, 2, 3, 4, 1.2, 2.4, 1.9f, "hello") val list2 = list.collect(partialFun) println("list2=" + list2) //第二种简写形式 val list3 = list.collect { case i: Int => i + 1 case j: Double => (j * 2).toInt case k: Float => (k * 3).toInt } println("list3=" + list3) // (2,3,4,5) } }
13.2 作为参数的函数
13.2.1 基本介绍
函数作为一个变量传入到另一个函数中,那么该作为参数的函数的类型是:function1,即:(参数类型) => 返回类型
13.2.2 应用案例
object boke_demo01 { def main(args: Array[String]): Unit = { def plus(x: Int) = 3 + x //说明 val result = Array(1, 2, 3, 4).map(plus(_)) println(result.mkString(",")) //4,5,6,7 //说明 //1. 在scala中,函数也是有类型,比如plus就是 <function1> println("puls的函数类型function1" + (plus _)) } }
13.2.3 对案例演示的小结
1) map(plus(_))中的plus(_)就是将plus这个函数当作一个参数传给了map,_这里代表从集合中遍历出来的一个元素
2) plus(_)这里也可以写成plus表示对Array(1,2,3,4)遍历,将每次遍历的元素传给plus的x
3) 进行 3+x 运算后,返回新的Int,并加入到新的集合result中
4) def map[B,That](f:A=>B)的声明中