大数据开发Scala函数式编程(第二十八篇)

1,059 阅读5分钟

一、什么是函数式编程

  1. Scala是一门既面向对象,又面向过程的语言
  2. 在Scala中,函数与类、对象一样,都是一等公民。Java中,函数不能脱离类存在的
  3. Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量
  4. Scala的语法规定:将函数赋值给变量时,必须在函数后面加上空格和下划线
1.1、匿名函数
  1. Scala中的函数也可以不需要命名,这种函数称为匿名函数
  2. 匿名函数的语法格式:(参数名:参数类型)=>函数体
  3. 可以将匿名函数直接赋值给某个变量
//匿名函数
val sayHelloFunc = (name: String) => println("Hello " + name)
1.2、高阶函数
  1. 由于函数是一等公民,所以我们可以直接将某个函数作为参数传入其他函数
  2. 接收其他函数作为当前函数的参数,当前函数也被称为高阶函数
  3. 高阶函数可以自动推断出它里面函数的参数类型,对于只有一个参数的函数,还可以省去小括号
package com.strivelearn.scala.scalafunction/**
 * @author strivelearn
 * @version MyFunction.java, 2022年11月13日
 */
class MyFunction {
  //匿名函数
  val sayHelloFunc = (name: String) => println("Hello " + name)
​
  //高阶函数
  def sayHello(func: (String) => Unit, name: String): Unit = {
    func(name)
  }
}
​
object MyFunction {
  def main(args: Array[String]): Unit = {
    val function = new MyFunction()
    function.sayHello(function.sayHelloFunc, "World")
  }
}
1.3、常用的高阶函数
  1. map

    对传入的每个元素都进行处理,最终会返回一个元素

  2. flatMap

    对传入的每个元素都进行处理,返回一个或者多个元素

  3. foreach

    对传入的每个元素都进行处理,没有返回值

  4. filter

    对传入的每个元素都进行一个条件判断,做过滤

  5. reduceLeft

    类似hadoop的reduce,进行聚合,从左侧开始进行聚合操作

二、词频统计

package com.strivelearn.scala.highorder
​
/**
 * @author strivelearn
 * @version WordCount.java, 2022年11月13日
 */
object WordCount {
  def main(args: Array[String]): Unit = {
    val str = "hello you hello me"
    val str1 = "hello hehe hello haha"
    val list = List(str, str1)
    //map简写
    list.flatMap(_.split(" ")).map(word => (word, 1))
    //map 这边定义一个元祖
    val i = list.flatMap(_.split(" ")).map((_, 1)).map(tup => tup._2).reduceLeft(_ + _)
    println(i)
  }
}

三、Scala的高级特性

3.1、模式匹配
  1. Scala没有Java种的switch case语法,但是,Scala提供了更加强大的match case语法,即模式匹配
  2. Java的switch case仅能匹配变量的值,Scala的match case可以匹配各种情况,比如:变量的类型,集合的元素,有值没有值
  3. 语法格式:变量 match{case 值=>代码}
  4. 在match case只要有一个分支满足条件,就不会走其他分支,与Java不一样,Java需要使用break语法
package com.strivelearn.scala.highorder
​
import java.io.{FileNotFoundException, IOException}
​
/**
 * @author strivelearn
 * @version Demo.java, 2022年11月13日
 */
object Demo {
  def test(day: Int): Unit = {
    day match {
      case 1 => println("星期一")
      case 2 => println("星期二")
      case 3 => println("星期三")
      case 4 => println("星期四")
      case 5 => println("星期五")
      case 6 => println("星期六")
      case 7 => println("星期日")
      case _ => println("none")
    }
  }
​
  def processException(e: Exception): Unit = {
    e match {
      case e1: FileNotFoundException => println("FileNotFoundException")
      case e2: IOException => println("IOException")
      case _: Exception => println
    }
  }
​
  def main(args: Array[String]): Unit = {
    test(1)
    processException(new IOException)
  }
}
​
3.2、case class
  1. case class称为样例类,类似于Java中的JavaBeaen,只定义field。Scala自动提供getter和setter方法,没有method
  2. case class的主构造函数接收的参数通常不需要使用var或者val修饰,Scala会自动使用val修饰
  3. Scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接收主构造函数中相同的参数并返回case class对象
package com.strivelearn.scala.caseclass
​
/**
 * @author strivelearn
 * @version Person.java, 2022年11月13日
 */
class Person {
​
}
​
case class Student(name: String, cla: String) extends Personcase class Teacher(name: String, sub: String) extends Person
package com.strivelearn.scala.caseclass
​
/**
 * @author strivelearn
 * @version Test.java, 2022年11月13日
 */
object Test {
  def check(p: Person): Unit = {
    p match {
      case Teacher(name, sub) => println(name + " " + sub)
      case Student(name, cla) => println(name + " " + cla)
      case _ => println("none")
    }
  }
​
  def main(args: Array[String]): Unit = {
    check(new Student("zhangsan", "class1"))
  }
}
3.3、Option与模式匹配
  1. Option有两种值,Some->表示有值,None->表示没值
  2. Option通常会用于模式匹配中,用于判断某个变量是有值还是没值,这比null更加简洁明了
def main(args: Array[String]): Unit = {
  val stringToInt = Map("a" -> 1, "b" -> 2)
  //直接报错。java.util.NoSuchElementException: key not found: a1
  //val i = stringToInt("a1")
  val maybeInt = stringToInt.get("a1")
  //输出None
  println(maybeInt)
}
def getAge(key: String, map: Map[String, Int]): Unit = {
  val age = map.get(key)
  age match {
    case Some(age) => println("age: " + age)
    case None => println("none")
  }
}
3.4、隐式转换
  1. Scala的隐式转换,允许手动指定将某种类型的对象转换为其它类型的对象
  2. Scala的隐式转换,最核心的就是定义隐式转换函数,即implicit conversion function
  3. 隐式转换函数与普通函数唯一的语法区别是要以implicit开头而且最好要定义函数返回类型
Scala默认会自动使用两种隐式转换
  1. 源类型:或者目标类型的伴生对象里面的隐式转换函数
  2. 当前程序作用域内可以用唯一标识符表示的隐式转换函数
  3. 如果隐式转换函数不在上述两种情况下,那么就必须手动使用import语法引入某个包下的隐式转换函数
  4. 建议:仅仅在需要进行隐式转换的地方
隐式转换案例:让狗会飞
package com.strivelearn.scala.test

import scala.language.implicitConversions

/**
 * @author strivelearn
 * @version Dog.java, 2022年11月13日
 */
class Dog(val name: String) {

  implicit def obj2Bird(obj: Object): Bird = {
    if (obj.getClass == classOf[Dog]) {
      val dog = obj.asInstanceOf[Dog]
      new Bird(dog.name)
    } else null
  }
}

object DogTest{
  def main(args: Array[String]): Unit = {
    val dog = new Dog("旺财")
    val bird = dog.obj2Bird(dog)
    bird.fly()
  }
}
package com.strivelearn.scala.test

/**
 * @author strivelearn
 * @version Bird.java, 2022年11月13日
 */
class Bird(val name: String) {
  def fly() {
    println(name + "can fly")
  }
}

旺财can fly