加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala002

发布时间:2020-12-16 08:45:46 所属栏目:安全 来源:网络整理
导读:Scala面向对象编程 1.课程目标 掌握Scala中面向对象编程 掌握Scala模式匹配 掌握Scala泛型高级内容 熟悉Scala中多线程编程模型 2.Scala 类 格式: class 名称{ //成员变量 //成员方法 } 使用类: 创建对象: val/var 对象名称=new 类名() //可写可不写 小括

Scala面向对象编程

1.课程目标

  • 掌握Scala中面向对象编程
  • 掌握Scala模式匹配
  • 掌握Scala泛型高级内容
  • 熟悉Scala中多线程编程模型

2.Scala 类

  • 格式:
      class 名称{
           //成员变量
           //成员方法
        }
     使用类:
      创建对象:
          val/var 对象名称=new 类名() //可写可不写  小括号中没有任何参数的时候 可以不用写
    
    package cn.itcast.day02
    
    import scala.collection.mutable.ArrayBuffer
    
    /**
      * 构建类
      * Person
      * 属性: name  不可变的
      * age  是可变的
      * skill 数组类型的
      * 方法:
      * add 添加技能
      * scanSkill 遍历技能
      */
    
    class Person {
      // name
      val name = "itcast"
      var age = 10
    
      val skill = new ArrayBuffer[String]()
    
      def add(str: String): Unit = {
        skill += str
      }
    
      def scanSkill(): Unit = {
        skill.foreach(x => println(x))
      }
    }
    
    object Scala_day02_class {
      def main(args: Array[String]): Unit = {
        val person = new Person
        println(person.name)
        println(person.age)
        person.add("scala")
        person.scanSkill()
      }
    }
    注意:
    1.class 没有public修饰,默认的权限都是public
    2.类名和文件名称没有任何关系

3.scala中setter getter

  • package cn.itcast.day02
    
    /**
      * 类 Student
      */
    class Student {
      //val 修饰的属性 只有getter权限 没有setter
      val name = "itcast"
      //var 属性既有getter 也有setter
      private var _age: Int = 10
    
      //age的setter 方法
    
      def age_(age: Int): Unit = {
        this._age = age
      }
    
      //age getter方法
    
      def age = this._age
    }
    
    
    object Scala_day02_gettersetter {
      def main(args: Array[String]): Unit = {
        val student = new Student
        println(student.name)
        student.age_(30)
        println(student.age) //访问的是age的getter方法
      }
    }
    注意: getter方法中 省略了小阔号 省略了返回值类型。 
    方法定义原则: 当一个方法只返回数据,而不进行业务逻辑处理的时候 此时 方法名称后()可以省略。可以理解成 通过def 定义一个属性。
  1. Scala中方法调用原则
  • /**
      * 类 Teacher
      * 方法 teach 参数 是String
      */
    class Teacher {
      def teach(suject: String): Unit = {
        println(s"教学$suject")
      }
    
       def teach2(suject: String = "java"): Unit = {
        println(s"教学$suject")
      }  
    }
    
    object Scala_day02_method {
      def main(args: Array[String]): Unit = {
        val teacher = new Teacher
        teacher.teach("scala")
    
        teacher teach ("scala")
    
        teacher teach "scala"
        teacher.teach2()
      }
    }
    注意:0 to 10 ,0 unitl 10 , 1 + 2  
     1.“对象  方法名称  参数” 这种调用形式:这种调用形式 只适用于一个参数的方法
     2.方法的参数可以指定默认值,并且在方法调用的时候 省略参数的传递

5.Scala中构造函数

  • 第一种: 主构造器
     定义格式: class 类名(参数列表*)
    第二种: 辅助构造器 定义在类的内部
    定义格式:
      def this(参数列表){
            //第一行代码必须是调用主构造器
            this(参数列表)  //class 类名(参数列表*)
        }
    package cn.itcast.day02
    
    /**
      * Animal
      */
    class Animal(val name: String) {
      var color: String = _
      var legs: Int = _
    
      //创建辅助构造器
      def this(name: String,color: String,legs: Int) {
        this(name)
        this.color = color
        this.legs = legs
      }
    
      //创建多个辅助构造器
      def this() {
        this("itcast")
      }
    }
    object Scala_day02_constructor {
      def main(args: Array[String]): Unit = {
        val animal = new Animal() //辅助构造器
        val cat = new Animal("cat") //调用主构造器
        val cat2 = new Animal("cat","yellow",4) //辅助构造器
        println(cat)
        println(cat2)
        println(animal)
        println(animal.name)
      }
    }
    
    注意: 主构造器有且仅有一个
        辅助构造器可以具有多个
        主构造器中参数 如果有val 修饰的话 public 如果有没有 private
  1. scala中单例对象
  • 单例对象: 在一个应用程序中,一个类只会创建一个对象,那么这个对象就是单例对象
    格式:object 对象名称{
        //成员变量
        //成员方法
    }
    使用:
      对象名称.成员变量
      对象名称.成员方法
      这种操作 类似于java中static 修饰的方法和属性的调用
    使用场景:
      主要最为工具对象使用 类似于java中 Util类
    
    object CommonUtil {
      val SUNDAY = "sunday"
    
      def getDate = new Date
    }
    
    object Scala_day02_object {
      def main(args: Array[String]): Unit = {
        println(CommonUtil.SUNDAY)
        println(CommonUtil.getDate)
      }
    }

7.伴生对象和伴生类

  • 如果一个object (单例对象)的名称与一个class (类)的名称相同,并且object和class 在同一个文件之下,那么则这个objec 就称之为 class的伴生对象,这个class 就称之为对象伴生类
    
    //创建类 SoftEngineer
    /**
      * 互为伴生的类与对象之间功能:
      *   1.能够互相访问其私有的变量和私有方法
      *   2.在伴生对象中有一个特殊方法 apply.通过apply方法 可以实现伴生对象的构造函数功能
      */
    class SoftEngineer(val exp: Int) {
      private val salary = "15K"
    
      def getHasHair = SoftEngineer.hasHair
    }
    
    object SoftEngineer {
      private val hasHair = true
    
      def getSalary = {
        val engineer = new SoftEngineer(10)
        engineer.salary
      }
    
      def apply(exp: Int): SoftEngineer = new SoftEngineer(exp)
    }
    
    object Scala_day02_objectclass {
      def main(args: Array[String]): Unit = {
        val engineer = SoftEngineer(10)
        println(engineer.getHasHair)
      }
    }
  1. main函数
  • 1.main 作为入口函数 存在于object中
    2.scala中 提供了另外一种代替main函数的方法
      extends App
    
    object Scala_day02_main extends App {
      println("helloword")
      println(args(0))  //通过args 变量接受初始化参数
    }

9.scala中继承关系

  • 继承关系  功能跟java一致
      class 父类
    继承: class 子类 extends 父类
     1.子类可以继承父类非私有的属性和方法
     2.子类可以覆盖父类的方法和属性  注意: var修饰的变量不能够被覆盖 可以直接修改,并且不能够使用super关键词直接调用
     3.子类可以访问父类的方法和属性 super关键词
     4.父类的引用可以指向子类的对象
     5.scala中继承关系也是单继承
    
    class BigDataEngineer {
      val exp: Int = 10
      var name: String = "bigdata"
    
      def word(): Unit = {
        println("开发项目")
      }
    }
    
    class HadoopEngineer extends BigDataEngineer {
      override val exp: Int = 15
      name="hadoop bigdata"
      override def word(): Unit = {
       // println(super.name)
        super.word()
        println("开发hadoop项目")
      }
    }
    
    object Scala_day02_extends {
      def main(args: Array[String]): Unit = {
        val engineer = new HadoopEngineer
        println(engineer.exp)
        println(engineer.name)
        engineer.word()
      //父类的引用指向子类的对象
        val engineer2: BigDataEngineer = new HadoopEngineer
        println(engineer2.exp)
      }
    }
    问题:子类在创建对象的时候,有没有创建父类的对象? 有的,子类创建对象的时候创建了父类的对象,子类的构造函数调用了父类的构造函数。

10.scala构造机制

  • 构造机制:直接在类中执行的一些语句,在构造函数调用完毕之后直接执行构造语句
    class 类名{
       println("sfsdfsd") //构造语句 
    }
    
    class Parent{
      println("我是父类")
    }
    class Son extends Parent {
      println("我是子类")
    }
    
    object Scala_day02_constructor2 {
      def main(args: Array[String]): Unit = {
        val son = new Son
      }
    }

11.子类调用父类有参的构造函数

  • 第一种情况:
      子类构造函数无参 父类的构造函数有参数
    第二种情况:
      子类构造函数有参数 父类构造函数也有参数
    class PC(val memory: Int,val cpu: Int)
    
    //子类
    class NotePC extends PC(memory = 100,cpu = 100)
    
    class DeskPC(memory: Int,cpu: Int) extends PC(memory,cpu)
    
    object Scala_day02_parent {
      def main(args: Array[String]): Unit = {
        val c = new NotePC
        println(c.memory)
        println(c.cpu)
        val dc = new DeskPC(120,130)
        println(dc.memory)
        println(dc.cpu)
      }
    }

12.抽象类

  • 定义: abstract class 类名{
        1.可以定义抽象方法和非抽象方法
        2.定义抽象属性和非抽象属性
        3.子类可以覆盖抽象父类的方法和属性
        4.如果一个方法 使用final修饰,子类不能够覆盖
    }
    abstract class AbstractClass(val name: String) {
      val exp: Int //抽象属性
      def work(): Unit //抽象方法不能省略返回值类型
    }
    
    class AbstractClassImpl(name: String) extends AbstractClass(name) {
      override val exp: Int = 10
    
      override def work(): Unit = {
        println("工作")
      }
    }
    object Scala_day02_abstract extends App {
      private val impl = new AbstractClassImpl("itcast")
      println(impl.exp)
      impl.work()
    
    }

13.匿名内部类

  • 匿名内部类:
      匿名内部类一般都具有临时性, 在使用过程中一般解决临时性的需求。
    object Scala_day02_innerclass {
      def main(args: Array[String]): Unit = {
        val engineer = new ScalaEngineer
        println(engineer.getClass)
        val scalaEngineer = new ScalaEngineer {
          def workByPython(): Unit = {
            println("开发python项目")
          }
        }
        scalaEngineer.workByPython()
        println(scalaEngineer.getClass)
      }
    }

14.强制类型转换

  • 子类继承父类以后,父类的引用可以指向子类的对象,此时父类的引用具备了多态特性。多态会引起一个比较种问题,就是类型转换异常。
    
     语法:
      对象.asInstanceOf[Class类名]
     判断类型:
      对象.isIntanceOf[Class类名]  //模糊形式的判断
      对象.getClass==classOf[类名] //精准判断
    
    class Employee {
      def work(): Unit = {
        println("工作")
      }
    }
    
    class ItEmployee extends Employee {
      def workByPc(): Unit = {
        println("开发IT项目")
      }
    }
    
    
    object Scala_day02_TypeTransaction {
      def boss(employee: Employee): Unit = {
        // employee.work()
        if (employee.getClass == classOf[Employee]) {
          val itEmployee = employee.asInstanceOf[ItEmployee]
          itEmployee.workByPc()
        } else {
          println("回家等消息")
        }
      }
      def main(args: Array[String]): Unit = {
        val employee: Employee = new ItEmployee
        boss(employee)
      }
    }
  1. 超类
  • Any: 所有类型的超级父类
      AnyRef: 所有引用类型的超级父类 Person 、Map List
      AnyVal: 所有值类型的超级父类 (Int、Double、Float)

16.特质

  • 特质功能:
      1.特质可以作为java中接口使用
      2.特质可以作为抽象类使用
      3.特质可以扩展对象的方法功能
      4.特质可以改造某个特定的方法功能
    格式:
      trait 名称 {
            内容
        }
  • 特质可以作为java中接口使用
    • package cn.itcast.day02
      
      /**
        * 特质可以作为java中接口使用
        *   1.可以定义抽象方法
        *   2.接口可以多实现
        *   3.接口可以继承其他接口
        * with:混入特质
        */
      trait HelloTrait {
        def sayHelloByChinese(): Unit
      }
      
      trait HelloTrait2 {
        def sayHelloByHanguo(): Unit
      }
      
      trait HelloTrait3 extends HelloTrait2 {
        def sayHelloByTaiguo(): Unit
      }
      
      class HelloTraitImpl extends HelloTrait with HelloTrait3 {
        override def sayHelloByChinese(): Unit = {
          println("你好")
        }
      
        override def sayHelloByTaiguo(): Unit = {
          println("萨瓦迪卡")
        }
      
        override def sayHelloByHanguo(): Unit = {
          println("阿尼哈撒有")
        }
      }
      
      object Scala_day02_trait1 {
        def main(args: Array[String]): Unit = {
          val impl = new HelloTraitImpl
          impl.sayHelloByChinese()
          impl.sayHelloByHanguo()
          impl.sayHelloByTaiguo()
      
          val impl2:HelloTrait3=new HelloTraitImpl
          impl2.sayHelloByHanguo()
        }
      }
  • 特质可以作为抽象类使用
    • /**
        * 特质可以作为抽象类使用
        *   1.定义抽象方法
        *   2.定义抽象属性
        *   3.定义非抽象方法和属性
        */
      trait AbstactTrait {
        val name: String
        val age = 10
      
        def work(): Unit = {
          println("工作")
        }
      }
      
      class AbstactTraitImpl extends 类名 with AbstactTrait with 特质 {
        override val name: String = "itcast"
      
        override def work(): Unit = {
          println("覆盖方法")
        }
      }
      
      object Scala_day02_trait2 {
        def main(args: Array[String]): Unit = {
          val impl = new AbstactTraitImpl()
          println(impl.name)
          println(impl.age)
          impl.work()
        }
      }
      与抽象类区别:
          抽象类可以有构造函数,特质没有构造函数
          抽象类是单继承的 特质是多混入的
  • 特质可以扩展对象的方法功能
    • 格式:
          val 名称=new 类名 with 特质 with 特质
      
      class Tank {
        def shoot(): Unit = {
          println("发射")
        }
      }
      
      trait Aim {
        def aim(): Unit = {
          println("瞄准")
        }
      }
      
      trait Scan {
        def scan(): Unit = {
          println("扫描")
        }
      }
      
      trait Fly {
        def fly(): Unit
      }
      
      object Scala_day02_trait3 {
        def main(args: Array[String]): Unit = {
          val tank = new Tank with Aim with Scan with Fly {
            override def fly(): Unit = {
              println("飞起来")
            }
          }
          tank.scan()
          tank.aim()
          tank.shoot()
          tank.fly()
        }
      }
  • 特质可以改造某个特定的方法功能
    • class SuperTank {
        def shoot(): Unit = {
          println("发射")
        }
      }
      
      trait SuperAim extends SuperTank {
        override def shoot(): Unit = {
          println("瞄准")
          super.shoot()
        }
      }
      
      trait SuperScan extends SuperTank {
        override def shoot(): Unit = {
          println("扫描")
          super.shoot()
        }
      }
      //执行顺序是自右向左过程
      class SuperTankSon extends SuperTank  with SuperScan with SuperAim
      
      object Scala_day02_trait4 {
        def main(args: Array[String]): Unit = {
          val son = new SuperTankSon
          son.shoot()
        }
      }
      
      super:线性调用的关键词。并且super线性跟混入特质的顺序有关,并且线性调用是自右向左过程

17.模式匹配

  • 语法:
      选择器 match {
            case 匹配值 => { 业务逻辑 }
            case 匹配值 => { 业务逻辑 }
            case 匹配值 => { 业务逻辑 }
            case _ =>{默认业务逻辑}
        }
    注意:   case 一旦匹配上,直接返回,则不会贯穿到下一个case
    
    模式匹配的数据类型:
      值 
      数据类型
      数组
      列表
      tuple
      map
      自定义数据类型
  • scala中模式匹配之 值匹配
    • object Scala_day01_match {
        def main(args: Array[String]): Unit = {
          val arr=Array[String]("hadoop","scala","spark","java")
         // val value=arr((math.random*arr.size).toInt)
          val value="flink"
          println(s"value:$value")
      
          /**
            * 选择器 match {
            * case 匹配值 => { 业务逻辑 }
            * case 匹配值 => { 业务逻辑 }
            * case 匹配值 => { 业务逻辑 }
            * case _ =>{默认业务逻辑}   能够匹配一切数据以及一切数据类型
            * }
            */
          value match {
            case "hadoop" => println("匹配上hadoop")
            case "scala" => println("匹配上scala")
            case "spark" => println("匹配上spark")
            case "java" => println("匹配上java")
              //默认匹配
            case _ =>println("默认匹配")
          }
        }
      }
  • 模式匹配匹配数据类型
    • /**
        * 模式匹配 匹配数据类型
        */
      object MatchDataType {
        def main(args: Array[String]): Unit = {
          val arr = Array("hadoop",3.14,10,true)
          val value = arr((math.random * arr.size).toInt)
          println(s"value:$value")
          value match {
            case s: String => println(s"string:$s")
            case d: Double => println(s"double:$d")
            case i: Int => println(s"int:$i")
            case b: Boolean => println(s"boolean:$b")
          }
        }
      }
  • 匹配Array
    • // 模式匹配 Array
      object MatchArray {
        def main(args: Array[String]): Unit = {
          val arr = Array[String]("spark","hadoop","scala")
          arr match {
              case Array(_*) =>println("sfsddsfsfsdfdsffs")  //可以匹配所有Array
             //模糊匹配
            case Array(x,y,_*) => println(x+"t"+y+" 模糊匹配")
            case Array("spark",_*) => println("模糊匹配")
            //占位符匹配
            case Array(x,_,_) =>println(x+" 占位符匹配占位符匹配")
            case Array("spark",_) => println("占位符匹配占位符匹配")
            //精确匹配
            case Array(x,z) =>println(x+"t"+y+"t"+z)
            case Array("spark","scala") => println("精确匹配")
          }
        }
      }
  • 模式匹配List
    • // 模式匹配 List
      object MatchList {
        def main(args: Array[String]): Unit = {
          val list = List("hadoop",3.25)
          list match {
             case List(_*) => {} //能够匹配所有的LIst 
            case "hadoop"::10::3.25::Nil =>println(2)
            case  List(x,_*) =>println(x)
            case List(x,_) => println(x + "t" + y + " 占位符匹配占位符匹配")
            //精确匹配
            case List(x,z) => println(x + "t" + y + "t" + z)
            case List("hadoop",3.25) => println("1")
          }
        }
      }
  • 匹配Tuple
    • // 模式匹配 Tuple
      object MatchTuple {
        def main(args: Array[String]): Unit = {
          val tuple = (3.14,100)
          tuple match {
            case (x,_) => println(x + "t" + y)
            case (x,z) => println(x + "t" + y + "t" + z)
          }
        }
      }
  • 匹配map
    • // 模式匹配 Map
      object MatchMap {
        def main(args: Array[String]): Unit = {
          val map = Map("hadoop" -> 10,"scala" -> 20)
          val value = map.get("java")
          value match {
            case Some(x) => println("x:" + x)
            case None => println("None")
          }
        }
      }
  • 匹配自定义数据类型
    • 注意:这种匹配方式在spark框架中 普遍存在,应用非常广泛
      两种自定义数据类型
       样例类 
          case class 类名称(参数列表)
       样例对象
          case object 对象名称
      
      //样例类
      case class Test(name: String,age: Int)
      
      //样例对象
      case object TestObject
      
      object MatchSelfDataType {
        def main(args: Array[String]): Unit = {
          val arr = Array(Test("itcast",13),TestObject)
      
          val value = arr((math.random * arr.size).toInt)
          println(s"value:$value")
          value match {
            case Test(name,age) => println(name + "t" + age)
            case TestObject => println("匹配上样例对象")
          }
        }
      }

18.偏函数

  • 偏函数:函数体 或者方法体 是一个模式匹配的形式
    def 名称(参数) = 参数 match {
        case 匹配
    }
    
    val 名称: PartialFunction[输入数据类型,输出数据类型] ={
        case 匹配
    }
    
    /**
        * def 名称(参数) =参数 match {
        * case 匹配
        * }
        */
      def getInt(x: Int): Int = x match {
        case 10 => 10 * 10
        case 20 => 20 * 20 * 20
        case _ => 1000
      }
    
      def main(args: Array[String]): Unit = {
        val i = getInt(30)
        println(i)
      }
    
    val fun: PartialFunction[Int,String] = {
          case 10 => String.valueOf(10 * 10)
          case 20 => String.valueOf(20 * 20 * 20)
          case _ => String.valueOf(1000)
        }
        val str = fun(20)
        println(str)

19.泛型的逆变协变和非变

  • 规定类的泛型操作
    class 类名[T]   //非变
    class 类名[+T]  //泛型协变操作, 协变操作使得泛型之间有了与类相关的继承关系
    class 类名[-T]  //逆变操作
    
    class Apple 
    class RedApple extend Apple
    class Box[T] //泛型类
    
    问题: RedApple 是 Apple子类, Box[RedApple] 会不会是 Box[Apple]子类? 
     假设: Box[RedApple] 是 Box[Apple] 子类的话,那么
          val box:Box[Apple]=new Box[RedApple] 成立
    答案 :假设不成立
    
    总结:
      C[T]:如果B是A的子类 ,那么 C[A]与C[B] 没有关系 非变操作
      C[+T] :如果B是A的子类 那么 C[A]是C[B] 的父类  协变操作
      C[-T]:如果B是A的子类  那么C[A]是C[B]的子类 逆变操作

20.方法参数的上下界操作

  • 通过规定方法参数的上下界操作,可以规定方法参数的传入过程
    U>:A : 下界操作 U是A类本身或者其父类
    S<:A : 上界操作 S是A类本身或者其子类 
    class Man
    
    class OldMan extends Man
    class OOldMan extends OldMan
    
    class YoungMan extends Man
    
    class YYoungMan extends YoungMan
    
    class Sport {
      //适合老年人方法  规定方法下界 U 是oldMan的本身或者是其父类
      def taiji[U >: OOldMan](man: U): Unit = {
        println("打太极")
      }
    
      //适合年轻人  规定上界 S:代表的是YoungMan本身 或者其子类
      def bengji[S <: YoungMan](youngMan: S): Unit = {
        println("年轻人游戏")
      }
    }
    
    object Scala_day02_upanddown {
      def main(args: Array[String]): Unit = {
    
        /* val yman = new YoungMan
         val yyman = new YYoungMan
    
         val sport = new Sport
         sport.bengji(yyman)*/
        val sport = new Sport
        val man = new Man
        val yyman = new YYoungMan
        val oldMan = new OldMan
        //val ooldMan = new OOldMan
        sport.taiji(yyman)
    
      }
    }
    
    
    class SuperBox[+T,-S] {
      //上界方法
      def up[P <: S](s: S): Unit = {
      }
      def down[D >: T](d: D): Unit = {
      }
    }

21.Scala中并发编程

  • 并发编程:继承Actor类 实现actor中 act方法
    class Myactor(val name: String) extends Actor {
      override def act(): Unit = {
        for (i <- 0 to 20) {
          println(name + "--------" + i)
        }
      }
    }
    object Scala_day02_actor {
      def main(args: Array[String]): Unit = {
        val myactor = new Myactor("myactor1")
        val myactor2 = new Myactor("myactor2")
        myactor.start() //启动线程
        myactor2.start()
      }
    }
  • Actor消息机制
    • 发送消息:actor!消息内容
      接受消息:act方法中 通过创建recevier 方法接受消息
      
      class MyActor2 extends Actor {
        override def act(): Unit = {
          var flag = true
          while (flag) {
            receive {
              case "start" => println("启动线程")
              case "test" => println("测试")
              case "end" => flag = false
            }
          }
        }
      }
      
      object Scala_day02_Actor2 {
        def main(args: Array[String]): Unit = {
          val actor = new MyActor2
          actor.start()
          actor ! "start"
          actor ! "test"
          actor ! "end"
          actor ! "test"
        }
      }
      注意:while receiver 这种形式 每次接收消息的都会创建receiver对象。
      loop react机制 代理while receiver机制 提高程序运行效率
      
      class MyActor3 extends Actor {
        override def act(): Unit = {
          var flag = true
          loop {
            react {
              case "start" => println("启动线程")
              case "test" => println("测试")
              case "end" => exit() //退出当前进程
            }
          }
        }
      }
  • actor发送消息的方式
    • !:发送异步消息 并且无返回值
      !?: 发送同步消息 并且有返回值 返回值的类型就Any
      !! :发送异步消息 并且有返回值 Future[Any]
      
      同步消息:
          发送完消息以后,需要等待消息执行完成返回数据
      异步消息:
          发送完消息以后,直接返回,通过Future[Any]对象在未来的某一时刻拿到异步消息的返回值 
      
      /**
        * actor 发送同步和异步消息
        * 消息形式:样例类
        */
      case class SynsMsg(id: Int,msg: String,times: Long)
      
      case class AsynMsg(id: Int,times: Long)
      
      case class ReplayMsg(id: Int,msg: String)
      
      
      class MsgActor extends Actor {
        override def act(): Unit = {
          loop {
            react {
              case SynsMsg(id,msg,times) => {
                Thread.sleep(times)
                println(id + "t" + msg)
                //发送返回值
                sender ! ReplayMsg(id,msg + "----replay")
              }
      
              case AsynMsg(id,times) => {
                Thread.sleep(times)
                println(id + "t" + msg)
                sender ! ReplayMsg(id,msg + "----Asyn---replay")
              }
            }
          }
        }
      }
      
      object Scala_day02_actor3 {
        def main(args: Array[String]): Unit = {
          val actor = new MsgActor
          actor.start()
          /* val replayMsg: Any = actor !? SynsMsg(2,"黑马",1000)
           println(replayMsg.asInstanceOf[ReplayMsg].msg)
           val replayMsg2 = actor !? SynsMsg(1,"itcast",2000)
           println(replayMsg2.asInstanceOf[ReplayMsg].msg)*/
      
          val list = new ListBuffer[Future[Any]]()
          val futurnReplayMsg: Future[Any] = actor !! AsynMsg(3,"传智播客",10000)
          val futurnReplayMsg2: Future[Any] = actor !! AsynMsg(4,"黑马程序员",1000)
          list += futurnReplayMsg
          list += futurnReplayMsg2
          while (list.size > 0) {
            for (future <- list) {
              //判断future中是否存在数据
              if (future.isSet) {
                val msg: Any = future.apply() //拿到future中数据
                val tmpReplayMsg = msg.asInstanceOf[ReplayMsg]
                println(tmpReplayMsg.msg)
                //将已经完成任务future剔除掉
                list -= future
              }
            }
          }
        }
      }

22.基于Actor的wordcount案例

  • 需求:用 actor 并发编程写一个单机版的 WordCount,将多个文件作为输入,计算完成后将多 个任务汇总,得 到终的结果
  • 实现步骤:
    1. 编写读取文件,并统计文件wordcount的工具方法
    2. 实现actor 并通过loop react方式接受消息。利用 case class 样例类去匹配对应的操作 并将结果封装在样 例类中,通过sender返回消息
    3. 主线程汇总返回结果,并将结果保存在ListBu?er中
    4. 后对ListBu?er中数据进行全局汇总
    5. 汇总完成后,关闭所有线程
  • package cn.itcast.day02
    
    import java.io.File
    
    import scala.actors.{Actor,Future}
    import scala.collection.mutable.ListBuffer
    import scala.io.Source
    
    /** 需求:3个文件
      * 启动三个Actor 读取3个文件
      * 对这个三个文件中数据 word 进行统计
      * 打印统计结果
      * */
    case class Task(filePath: String)
    
    case class ReplayMap(map: Map[String,Int])
    
    class MyActor28 extends Actor {
      override def act(): Unit = {
        loop {
          react { case Task(filePath) => {
            val lines = Source.fromFile(new File(filePath)).getLines().toArray
            val groupByResult = lines.flatMap(x => x.split(",")).map(w => (w,1)).groupBy(t => t._1)
            val result = groupByResult.mapValues(a => a.length)
            sender ! ReplayMap(result)
          }
          }
        }
      }
    }
    
    object Scala_28_Actor {
      def main(args: Array[String]): Unit = {
        val arr = Array("D://a.txt","D://b.txt","D://c.txt")
        //装返回数据
        val list = new ListBuffer[Future[Any]]()
        val listReplayMap = new ListBuffer[ReplayMap]()
        for (filePath <- arr) {
          val a = new MyActor28()
          a.start()
          val result = a !! Task(filePath)
          list += result
        }
    
        //循环遍历接受数据的操作
        while (list.size > 0) {
          val flterReulst = list.filter(f => f.isSet)
          for (f <- flterReulst) {
            listReplayMap += f.apply().asInstanceOf[ReplayMap]
            list -= f
          }
        }
        val groupByListBuffer = listReplayMap.map(rm => rm.map).flatten.groupBy(t => t._1)
        //lb 是listBuffer (tuple)
        val wordcount = groupByListBuffer
          .mapValues(lb => {
            //t 代表 tuple
            // map(t=>t._2)  拿到tuple的value数据
            // x:初始值 0 y 第一个元素
            lb.map(t => t._2).reduce((x,y) => x + y)
          })
    
        for (wc <- wordcount) {
          println(wc)
        }
      }
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读