偏函数也是函数的一种,通过偏函数我们可以方便的对输入参数做更精确的检查。例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。
    1.偏函数定义
    注:该偏函数的功能是返回输入的List集合的第二个元素

    1. val second: PartialFunction[List[Int], Option[Int]] = {
    2. case x :: y :: _ => Some(y)
    3. }

    image.png

    2. 偏函数原理
    上述代码会被scala编译器翻译成以下代码,与普通函数相比,只是多了一个用于参数检查的函数——isDefinedAt,其返回值类型为Boolean

    1. val second = new PartialFunction[List[Int], Option[Int]] {
    2. //检查输入参数是否合格
    3. override def isDefinedAt(list: List[Int]): Boolean = list match {
    4. case x :: y :: _ => true
    5. case _ => false
    6. }
    7. //执行函数逻辑
    8. override def apply(list: List[Int]): Option[Int] = list match {
    9. case x :: y :: _ => Some(y)
    10. }
    11. }

    一步步变为偏函数

    1. // 1. map转换,实现key不变,value2倍
    2. val newList = list.map( tuple => (tuple._1, tuple._2 * 2) )
    3. // 2. 用模式匹配对元组元素赋值,实现功能
    4. val newList2 = list.map(
    5. tuple => {
    6. tuple match {
    7. case (word, count) => (word, count * 2)
    8. }
    9. }
    10. )
    11. // 3. 省略lambda表达式的写法,进行简化
    12. val newList3 = list.map {
    13. case (word, count) => (word, count * 2)
    14. }
    15. println(newList)
    16. println(newList2)
    17. println(newList3)
    1. 偏函数使用

    偏函数不能像second(List(1,2,3))这样直接使用,因为这样会直接调用apply方法,而应该调用applyOrElse方法,如下

    1. second.applyOrElse(List(1,2,3), (_: List[Int]) => None)

    applyOrElse方法的逻辑为 if (ifDefinedAt(list)) apply(list)else default,如果输入参数满足条件,即isDefinedAt返回true,则执行apply方法,否则执行defalut方法,default方法为参数不满足要求的处理逻辑

    1. 案例实操

    (1)需求
    将该List(1,2,3,4,5,6,“test”)中的Int类型的元素加一,并去掉字符串

    1. def main (args: Array[String] ): Unit = {
    2. val list = List (1, 2, 3, 4, 5, 6, "test")
    3. val list1 = list.map {
    4. a =>
    5. a match {
    6. case i: Int => i + 1
    7. case s: String => s + 1
    8. }
    9. }
    10. println (list1.filter (a => a.isInstanceOf[Int] ) ) // List(2, 3, 4, 5, 6, 7)
    11. }

    (2)实操
    方法一:

    1. List(1,2,3,4,5,6,"test").filter(_.isInstanceOf[Int]).map(_.asInstanceOf[Int] + 1).foreach(println)

    方法二:

    1. List(1, 2, 3, 4, 5, 6, "test").collect { case x: Int => x + 1 }.foreach(println)

    偏函数求绝对值

    // 偏函数的应用,求绝对值
    // 对输入数据分为不同的情形:正、负、0
    val positiveAbs: PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }
    val negativeAbs: PartialFunction[Int, Int] = {
      case x if x < 0 => -x
    }
    val zeroAbs: PartialFunction[Int, Int] = {
      case 0 => 0
    }
    
    def abs(x: Int): Int = (positiveAbs orElse negativeAbs orElse zeroAbs) (x)
    
    println(abs(-67))
    println(abs(35))
    println(abs(0))