14.1 偏函数


14.1.1 一个简单的需求

给你一个集合val list = List(1, 2, 3, 4, "abc")

请完成如下要求: 将集合list中的所有数字+1,并返回一个新的集合 要求忽略掉非数字的元素,即返回的新的集合形式为 (2, 3, 4, 5)

思路1: 使用filter + map

package com.atguigu.day12

object PianHanDemo1 {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, "abc")
    val list2: List[Int] = list.filter(f1).map(f2).map(f3)
    println(list2)
  }

  def f1(n: Any): Boolean = {
    n.isInstanceOf[Int]
  }

  def f2(n: Any): Int = {
    n.asInstanceOf[Int]
  }

  def f3(n: Int) = {
    n + 1
  }
}

思路2: 模式匹配

package com.atguigu.day12

object PianHanDemo2 {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, "abc")
    println(list.map(addOne))
  }

  def addOne(i: Any): Any = {
    i match {
      case x: Int => x + 1
      case _ =>
    }
  }
}

这种解决方法有问题!

如果想优雅的解决前面的需求(在对符合某个条件,而不是所有情况进行逻辑操作), 偏函数可以完美的满足我们!

14.1.2 偏函数基本概念

被大括号包含起来的一组case语句就是一个偏函数.

偏函数并非对所有的输入值都有定义.

偏函数是PartialFunction[A,B]特质的一个实例.(A 是参数类型, B是返回值类型)

1. 创建偏函数

package com.atguigu.day12

object ParDemo3 {
  def main(args: Array[String]): Unit = {

    val f1 = new PartialFunction[Any, Int] {
      // 接受传入的参数, 如果返回值值是true, 则会调用apply来创建对象
      override def isDefinedAt(x: Any): Boolean = x.isInstanceOf[Int]
      //
      override def apply(v1: Any): Int = v1.asInstanceOf[Int] + 1
    }

    val list = List(1, 2, 3, 4, "abc")
    val list2: List[Int] = list.collect(f1)
    println(list2)
  }
}

说明:

  • 创建偏函数需要重写两个方法:isDefinedAtapply

  • 接受传入的参数, 如果返回值值是true, 则会调用apply来创建对象, 如果false, 则不会调用apply方法, 相当于忽略了该元素.

  • 构建偏函数时,参数形式 [Any, Int]是泛型,第一个表示参数类型,第二个表示返回参数

  • 当使用偏函数时,会遍历集合的所有元素,编译器执行流程时先执行isDefinedAt()如果为true ,就会执行 apply, 构建一个新的Int 对象返回 执行isDefinedAt()false 就过滤掉这个元素,即不构建新的Int对象.

  • map函数不支持偏函数,因为map底层的机制就是所有循环遍历,无法过滤处理原来集合的元素

  • collect函数支持偏函数. 可以看成是filter + map

2. 创建偏函数的简写方式

package com.atguigu.day12

object ParDemo4 {
  def main(args: Array[String]): Unit = {

    val list = List(1, 2, 3, 4, "abc")
    // 简写方式1: 花括号内直接写case语句, 就是一个偏函数
    val f1: PartialFunction[Any, Int] = {
      case x: Int => x + 1
    }
    println(list.collect(f1))
    // 简写方式2:
    val list2: List[Int] = list.collect({ case x: Int => x + 1 })
    println(list2)
  }
}
Copyright © 尚硅谷大数据 2019 all right reserved,powered by Gitbook
该文件最后修订时间: 2019-07-02 08:12:45

results matching ""

    No results matching ""