Scala高阶函数学习

1 简介
  1. Scala函数式编程在scala中占据着重要地位,
  2. 函数与变量同等地位,函数的定义可以单独定义,可以不依赖于类、接口或者object,而且独立存在,独立使用,并且可以赋值给变量。
  3. Scala的函数式编程使得算法的设计可以更高效更精简,因为函数式是依赖人们的思考 方式构建的。
  4. Spark中的计算几乎所有都是用函数式编写的,而且我们在处理数据一般都是针对集合的,集合的函数式编程更是重中之重,以及基于scala的函数式操作集合。
2 高阶函数

**定义:**如果一个函数是一个函数的参数则称为此函数为高阶函数 ,高阶函数是scala与java的最大不同。例如,将函数赋值给一个变量。

2.1 把函数赋值给一个变量
//定义一个sayHello函数
scala> def sayHello(name:String): Unit = {
     |     println("Hello: " + name)
     |   }
sayHello: (name: String)Unit
//把函数复制给一个变量,函数名 _   中间一定要加空格
scala> var x=sayHello _
x: String => Unit = <function1>
//此时我们看出x就是函数了,参数的类型是String类型,返回值是Unit

scala> sayHello("Scala")
Hello: Scala
  • 匿名函数
    很多场景我们可能不需要函数名称,只需要函数执行的功能就可以了,这时候我们就会使用匿名函数。 但是我们要使用它,就可以借助函数赋值给变量,变量就变成了函数的性质,将匿名函数赋值给变量。
    **匿名函数的定义规则: **(参数 :类型) => 函数的操作
scala> val y=(text:String) => println(text)
y: String => Unit = <function1>

scala> y("hadoop")
hadoop
2.2 把函数作为函数的参数

因为函数的参数可以是变量,而函数又可以赋值给变量,即函数和变量地位一样,所以函数参数也可以是函数

scala> val sayHello = (text : String) => println(text)
hiScala: String => Unit = <function1>

scala> def test(func : (String) => Unit,content:String){func(content)}
bigData: (func: String => Unit, content: String)Unit

scala> test(sayHello,"Scala")
Scala

首先我们定义了一个函数test,这个函数有两个参数,第一个参数是一个函数,函数名是func,他有一个String类型的参数并且返回值是unit空的;第二个参数是String类型的变量名为content的变量,函数体是将第二个参数作为第一个参数也就是函数func的参数,来调用第一个函数,整个函数返回值为unit空。这里只要传入的函数的格式与定义的一致就行。

2.3 高阶函数的返回值作为函数
scala> def saySomething(str1:String) = (str2:String)=>{
     |     println(str1+":"+str2)
     |   }
saySomething: (str1: String)String => Unit
//可以看到定义上面的函数的含义是,传递一个String类型的参数,返回值也是String类型(类型推断机制)
scala> saySomething("a")
res0: String => Unit = <function1>
//这是我们执行函数saySomething并且传递一个字符串a,结果是不是很意外,结果竟然是得到一个函数,且输入类型是String,因为 (str2:String) 输入参数是String,返回类型是Unit;

//接下来我们继续执行下面的代码
//上面我们分析了其返回值也就是一个函数赋值了变量test,这样就得到了一个名为test的函数。
scala> val test:String=>Unit=saySomething("b")
test: String => Unit = <function1>
(得到的结果和我们分析的一样一样的)

//然后我们调用test函数得到了打印结果。
scala> test("a")
b:a
//这里应该很清楚了为什么打印结果是b:a了吧。

**总结:**首先我们调用了saySomething(“a”)传递了一个字符串a(a就是str1:String),得到的结果是一个函数,切传递的参数是String类型(即str2:String),然后我们又把test变量赋值给这个函数,得到test函数,最后调用test函数传递字符串"b",所以得到结果b:a。分析结束!

2.4 闭包

**定义:**函数的变量,超出他的有效作用域中我们还能对函数的内部变量进行访问。

scala> def scala(str1:String)=(str2:String)=>println(str1+" "+str2)
scala: (str1: String)String => Unit

scala> val Result=scala("Spark")
Result: String => Unit = <function1>

scala> Result("flink")
scala flink

上面分析了高阶函数的返回值作为函数这段代码应该小菜一碟了吧,下面我们分析另外一个问题,变量的作用范围。

  1. 在这里我们首先定义了返回值为函数的一个函数,然后我们调用了该函数,传入的参数为Spark,通常当函数scala运行结束后,我们是不能在访问该参数了,因为局部变量Spark的作用域也就是生命周期结束了,但是当我们调用Result函数后,发现它是能访问参数Spark的。这就是函数的闭包。scala内部是创建了一个函数的内部对象,将参数Spark作为一个成员保留在了这个对象中。
  2. 也就是说str1的内容被保存在函数体内部可以被反复的使用。
  3. 闭包的实现原理是:scala为我们当前的函数生成了一个当前我们看不到的对象,而scala函数也是对象的成员,当我们执行scala函数的时候,也就是执行对象里面的函数,而对象里面的函数,访问函数里面的属性成员是非常正常的。
2.5 颗粒化

作用是将两个参数的函数,转换成两个函数,第一个函数的参数为两个参数函数的第一个参数,同理,第二个函数的参数为第二个参数。

scala> def sum(x:Int,y:Int) = x + y
sum: (x: Int, y: Int)Int
scala> sum(1,2)
res3: Int = 3

scala> def sum_1(x:Int) = (y:Int) => x + y
sum_1: (x: Int)Int => Int
scala> sum_1(1)(2)
res5: Int = 3

scala> def sum_2(x : Int)(y : Int) = x + y
sum_2: (x: Int)(y: Int)Int
scala> sum_2(1)(2)
res6: Int = 3
2.6 集合
object Advanced_function extends App{
  //创建一个集合
    val l = List(1,2,3,4,5,6,7,8)

    // 所有元素*2, map: 把l里面的每个元素都做一个相同的操作
    l.map((x:Int) => print(x*2+" "))

//换行
println()

    // 参数的类型推断机制
    l.map((x) => print(x* 2+" "))

//换行
println()

    l.map(x => print(x*2+" "))

//换行
println()

    print(l.map(_*2)+" ")   // *****

//换行
println()

  //加上filter进行条件过滤
    print(l.map(_*2).filter(_>8)+" ")

//换行
println()

  //取前四个元素
    print(l.take(4)+" ")

//换行
println()

    // reduce:对元素x和元素y进行处理,使用后面的方法x+y进行处理,以此类推
    print(l.reduce((x,y)=>x+y))

//换行
println()

   print(l.reduce(_+_))  // *****

//换行
println()

  //分析过程
    l.reduceRight((x,y) =>{
      println(x + " , " + y)
      x - y
    })

//换行
println()

  //集合中大于三的元素个数
  print(l.count(_ > 3))

//换行
println()

  //faltten,flatMap,map区别
    val f = List(List(1,2),List(3,4),List(5,6))
  print(f.flatten)

//换行
println()

    print(f.flatMap(_.map(_*2)))   // map+flatten

//换行
println()

    print(f.map(_.map(_*2)))
}
2.7 映射

scala中的映射操作类似于java 中的Map

  • 不可变映射

scala> val map = Map("zhangsan" -> 1, "lisi" -> 2 , "wangwu" -> 3)
map: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 1, lisi -> 2,wangwu -> 3)

//元祖
scala> val map1 = Map(("zhangshan",1),("lisi",2),("wangwu",3))
map1: scala.collection.immutable.Map[String,Int] = Map(zhangshan -> 1, lisi -> 2, wangwu -> 3)
  • 可变映射
scala> val map2 = scala.collection.mutable.Map(("zhangshan",1),("lisi",2),("wangwu",3))
map2: scala.collection.mutable.Map[String,Int] = Map(lisi -> 2, wangwu -> 3, zha
ngshan -> 1)

//空映射
scala> val hashmap =new scala.collection.mutable.HashMap[String,String]
hashmap: scala.collection.mutable.HashMap[String,String] = Map()

  • 获取值
scala> map("zhangsan")
res9: Int = 1

scala> map("jack")
java.util.NoSuchElementException: key not found: jack
  at scala.collection.immutable.Map$Map3.apply(Map.scala:170)
  ... 28 elided

scala> map.contains("jack")
res11: Boolean = false

如果映射中没有值则会抛出异常. 可以使用contains方法进行检查.

  • 迭代映射
scala> for((key,value) <- map)
     | println(key + ":" + value)
zhangsan:1
lisi:2
wangwu:3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值