大数据之scala_scala(高阶函数 偏函数 匹配模式)

高阶函数

函数的参数是函数的函数或者方法
函数的返回值是函数的函数或者方法
函数的参数和返回值都是函数的函数或者方法
使用高阶函数的一个原因是减少冗余的代码。比方说需要写几个方法以通过不同方式来提升员工工资,若不使用高阶函数,代码可能像这样:

object SalaryRaiser {
  def smallPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * 1.1)

  def greatPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * salary)
}

有了高阶函数以后,可以使用在函数中传入逻辑性的代码(函数)即可 , 减少了代码的冗余性 !

函数或者方法的参数是函数

class HighFunction{
//在方法的参数中定义一个函数,f:String=>Int
  def m(s:String,f:String=>Int)={
    //使用该方法的第一个参数自己调用自己的函数
    f(s)
  }
}  

object HighFunction {
def apply(): HighFunction = new HighFunction()
def main(args: Array[String]): Unit = {
   //传入参数,并自定义函数的实现方式(字符串转为Int类型)
    val i: Int = HighFunction().m("123", x => x.toInt)
    println(i)  //123
}

函数的返回值是函数

class HighFunction{
//定义一个空参的方法,设置该方法的返回值为一个函数
  def m2(): String => Int = {

    f:String=>f.toInt

  }
}
object HighFunction {
  def apply(): HighFunction = new HighFunction()
  def main(args: Array[String]): Unit = {

    //使用方法一:先调用m2,然后m2会返回一个函数mf,我们再调用mf("123")
    val mf: String => Int = HighFunction().m2
    val i1: Int = mf("123")

    //使用方法二:在调用m2方法的时候,直接传入一个("2312"),该参数就会自动调用m2里面的函数,然后返回实现该函数的功能后的值
    val i2: Int = HighFunction().m2("2312")
  }
}
def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = {
  val schema = if (ssl) "https://" else "http://"
  (endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"
}

val domainName = "www.example.com"
def getURL = urlBuilder(ssl=true, domainName)
val endpoint = "users"
val query = "id=1"
val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String

偏函数

偏函数是一个特质 ,是专门用来处理一种类型数据用的
例如 将集合中的所有的Int类型的数据都加上1

//  方式一   过滤器形式
 val list = List(1, 2, 3, 4, "hello")
 val res: List[Int] = list.filter(x => x.isInstanceOf[Int]).map(x => x.asInstanceOf[Int] + 1)
 res.foreach(println)

 // 方式二   匹配模式
 val res2: List[Any] = list.map(x => x match {
   case x: Int => x + 1
   case _ =>
 })
 res2.filter(x => x.isInstanceOf[Int]).foreach(println)

// 方式三  使用偏函数  泛型1 输入的数据类型 泛型2 要处理的数据类型
 val pp = new PartialFunction[Any,Int] {
   // 返回true
   override def isDefinedAt(x: Any) = {
     x.isInstanceOf[Int]
   }
   // 执行下一个方法
   override def apply(v1: Any) = {
     v1.asInstanceOf[Int]+1
   }
 }

  //  list.map(pp).foreach(println)
  list.collect(pp).foreach(println)

偏函数的执行流程
偏函数的执行流程
1 遍历list中的每个元素
2 调用 val e = if (isDefinedAt) {apply}
3 每得到一个e 就会将e存储在一个新的集合中 返回
使用偏函数就不要使用map方法了
偏函数总结
1)使用构建特质的实现类(使用的方式是PartialFunction的匿名子类)
2)PartialFunction 是个特质(看源码)
3)构建偏函数时,参数形式 [Any, Int]是泛型,第一个表示参数类型,第二个表示返回参数
4)当使用偏函数时,会遍历集合的所有元素,编译器执行流程时先执行isDefinedAt()如果为true ,就会执行 apply, 构建一个新的Int 对象返回
5)执行isDefinedAt() 为false 就过滤掉这个元素,即不构建新的Int对象.
6)map函数不支持偏函数,因为map底层的机制就是所有循环遍历,无法过滤处理原来集合的元素
7)collect函数支持偏函数

偏函数的简写形式

val list = List(2, 4, 6, 8, "cat")

//定义一个偏函数
def myPartialFunction: PartialFunction[Any, Int] = {
  case x: Int => x * x
}
list.collect(myPartialFunction).foreach(println)
****// 简写方式 
list.collect({
  case x:Int=>x*x
}).foreach(println)

匹配模式

模式匹配,其实类似于Java中的swich case语法,即对一个值进行条件判断,然后针对不同的条件,进行不同的处理。
但是Scala的模式匹配的功能比Java的swich case语法的功能要强大地多,Java的swich case语法只能对值进行匹配。但是Scala的模式匹配除了可以对值进行匹配之外,还可以对类型进行匹配、对Array和List的元素情况进行匹配、对case class进行匹配、甚至对有值或没值(Option)进行匹配。
而且对于Spark来说,Scala的模式匹配功能也是极其重要的,在spark源码中大量地使用了模式匹配功能。
基本语法

_  match {
case _ 2 => TODO
case _1 => TODO
case _ => 
}

/**
  * 牛逼的匹配模式
  *
  * @param arg
  */
def test1(arg: Any) = arg match {
  case x: Int => println("输入的参数是一个Int类型")
  case x: (String, Int) => println(s"输入的是一个元组:$x")
  case arr: Array[Int] => println(s"这是一个数组: " + arr(0))
  case _ => println("我不知道你是个啥")
}

字符串
匹配模式可以对字符串进行内容匹配!!

def test3(arr:Array[String]): Unit ={
  // 生成一个随机的整数数据  随机取出数组中的一个元素 
   val index: Int = Random.nextInt(arr.length)
  arr(index) match  {
    case "DOIT_TAOGE" => println("涛哥")
    case "DOIT_XINGGE" => println("星哥")
    case "DOIT_XIAOHANG" => println("小行")
    case "DOIT_NANA" => println("娜姐")
    case _ => println("这个是小胡")
  }
}
def main(args: Array[String]): Unit = {
  val arr = Array[String]("DOIT_TAOGE","DOIT_XINGGE","DOIT_XIAOHANG","DOIT_NANA","DOIT_CLS")
 test3(arr)
}

数据类型

def test4(arr:Array[Any]){
  // 生成一个随机的整数数据  随机取出数组中的一个元素
  val index: Int = Random.nextInt(arr.length)
  arr(index) match  {
    case m: Map[_, _] => "Map:" + m.size
    case t: (_, _) => "Tuple2: " + t._1 + "," + t._2
    case x:Int => //TODO
    case x:String=> print("哈哈哈")//TODO
    case x:Double => //TODO
    case x:Boolean=> //TODO
    case Person=> //TODO
    case _ =>  //TODO
  }
}

元组

/**
  * 匹配元组
  *   同时可以匹配指定元组元素的数据类型
  * @param arg
  */
def tupleMatch(arg:Any): Unit ={
  arg match {
    case (x:Int,y:Int)=> print(s"IntType:$x , $y")
    case(x:String ,y:String)=>print(s"Stringtype: $x , $y")
    case (x,y,z) =>print(s"$x , $y , $z")
    case _ =>print(s"wakaka~~")
  }
}

List和Array
数组

val arr: Array[Any] = Array[Any]("abc",12,3,4,5,6)
arr match {
 /case Array(x,_,_,_,_,_) => print(s"$x")
  case  Array("abc",_*) =>print("这个数组是以字符串abc开头 : "+arr.length)
  case _ => println("hah")
}

List

 val lst = List(3, 5, 6, 7)
    lst match {
      case 1 :: x :: y => println(s"x=${x},y=${y}")
      case List(x, y, z, d) => println("match ")
      case x :: y :: c :: d :: z => println(s"x=${x},z=${z}")
      case _ => println("no match ")
    }

样例类和样例对象

abstract class Animal
case class  Cat(name: String) extends Animal
case class  Dog(name: String) extends Animal
case class  Monkey(name: String) extends Animal
case object Hours(name: String) extends Animal
/**
  * 匹配样例类
  * @param arg
  * @return
  */
def test2(arg: Any) = arg match {
  case Cat(_) => ("这是一只猫" + arg)
  case Dog(_) => ("这是一只狗" + arg)
  case Monkey(_) => ("这是一只猴子" + arg)
  case _ => ("这是个啥玩意??")
}
//测试
println(test2(Cat("喵...")))
println(test2(Dog("汪...")))
println(test2(Monkey("咯咯...")))
println(test2(Hours("呃呃")))

Option

val map = Map("yangzi"->27,"reba"->30 ,"yangmi"->41)
val res: Int = map.get("fengjie") match {
  case Some(v) => v
  case None => -1
}
println(res)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值