scala面向对象

Scala面向对象编程

1.课程目标

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

2.面向对象

2.1 类
  • 定义: class 类名{
        	成员变量
        	val/var 名称=值
        	成员方法
        	def 方法名称(参数列表):返回值={
                方法体
            }
    	}
    创建对象:
    	val 对象名称=new 类名() //() 可写可不写  ()没有参数的时候可以省略
    
    /**
      * Person
      * name 不可变
      * age  可变
      * skill 数组
      * 方法:
      * def addSkill
      * def scanSkill
      */
    class Person {
      val name = "itcast"  //不可变 不需要setter 
      var age = 13  //可变 需要setter getter
      val skill = new ArrayBuffer[String]()
    
      // def addSkill
      def addSkill(subject: String): Unit = {
        skill += subject
      }
    
      def scanSkill(): Unit = {
        skill.foreach((x: String) => println(x))
      }
    }
    
    
    object Scala_01_class {
      def main(args: Array[String]): Unit = {
        val person = new Person
        println(person.name)
        person.age=14
        println(person.age)
        person.addSkill("scala")
        person.addSkill("spark")
        person.scanSkill()
      }
    }
    
2.2 setter getter
  • /**
      * Student类
      * name 不可变
      * age 可变
      *
      * 注意:
      *   1.如果一个方法 只返回结果 在方法内部不进行任何业务逻辑处理的话,就可以省略方法名称后边的小括号“()”
      *   2.通过def 定义属性
      */
    
    class Student {
      val name = "itcast" //不需要提供setter 和getter
      private var _age = 10 //可变变量定义格式 : _名称
      //setter
      def age_(age: Int) = this._age = age
    
      //getter
      def  age=this._age
    }
    
    object Scala_02_class {
      def main(args: Array[String]): Unit = {
        val student = new Student
        student.age_(10)
        println(student.age)
      }
    }
    
2.3 方法的调用原则
  • /**
      * Teacher 类
      *   teach方法
      *
      *   注意:teacher teach "spark" 这种调用方式只适用于一个参数的方法
      */
    class Teacher{
      def teach(suject:String): Unit ={
        println(s"教学:$suject")
      }
    }
    
    object Scala_03_class {
      def main(args: Array[String]): Unit = {
        val teacher = new Teacher
        teacher.teach("hadoop")
        teacher teach("scala")
        teacher teach "spark"
        0 to 10 
        0 until 10
        1 + 2
      }
    }
    
2.4 Scala构造器
  • 两种构造器方式
    	主构造器
    		class 类名(参数*)
    	辅助构造器
    		定义在类当中
    		def this(参数*){
                //第一行代码必须代用主构造
                this(参数)
            }
    /**
      * 定义: Animal
      * 主构造器 (name)
      * 辅助构造(color,legs)
      */
    class Animal(val name: String) {
      var _color = "red"
      var _legs = 2
    
      //辅助构造(name,color,legs)
      def this(name: String, color: String, legs: Int) {
        this(name) //调用主构造器
        this._color = color
        this._legs = legs
      }
    }
    
    object Scala_04_class {
      def main(args: Array[String]): Unit = {
        val a=new Animal("dog")
    
        val b=new Animal("cat","white",2)
    
        println(a.name)
        println(b._legs)
      }
    }
    
2.5 Scala中单例对象
  • 创建方式:
    	object 名称{
            成员变量
            成员方法
        }
    使用方式:
    	可以通过 名称.成员变量/成员方法 形式使用。相当于java中static修饰变量和方法的调用
     应用场景:
    	单例对象多应用于工具类或者工具对象
    //创建工具对象
    object CommonUtil {
      val PI = 3.14
    
      def getDate = new Date
    }
    
    object Scala_05_object {
      def main(args: Array[String]): Unit = {
        println(CommonUtil.PI)
        println(CommonUtil.getDate)
      }
    }
    
2.6 伴生对象
  • 当单例对象的名称跟类名相同的时候,并且单例对象和类同时存在于同一个文件中, 这里这个对象就称之为类的伴生对象。类是对象的伴生类
    
    /**
      * SoftEngineer 类
      * SoftEngineer  object
      * 1.伴生类和伴生对象之间可以互相访问 private属性和方法
      * 2.apply存于伴生对象中 能够实现伴生类创建对象的功能 ,相当于java中的工厂模式的定义
      */
    class SoftEngineer(val exp:Int){
      private var salary=1000
      def getHasGF()={
        SoftEngineer.hasGF //访问伴生对象中私有变量
      }
      val hasHair=SoftEngineer.hasHair()
    
    }
    
    object SoftEngineer{
      private var hasGF=false
      //定义方法 访问伴生类的私有变量
      def getSalary()={
        val engineer = new SoftEngineer(10)
        engineer.salary  //访问私有变量
      }
      private def hasHair()={
        true
      }
    
      def apply(exp:Int): SoftEngineer = new SoftEngineer(exp)
    }
    
    
    object Scala_06_object {
      def main(args: Array[String]): Unit = {
        val engineer = new  SoftEngineer(10)
        println(engineer.getHasGF())
        println(engineer.hasHair)
        println( SoftEngineer.getSalary())
    
        val engineer2 = SoftEngineer(10) //Array(“dd”) List("ddd")
      }
    }
    
2.7 main函数
  • //通过继承App的方式可以省略掉main 
    //本质上 还是没有省略 App中包含main函数
    object Scala_07_object extends App {
      println("hello app")
      println(args(0))
    }
    
2.8 继承
  • 格式:class 类名 extends 父类
    1.scala单继承
    2.子类可以继承父类的非私有的属性和方法
    3.子类可以重写父类的方法和属性
    4.子类可以通过super关键词调用父类的属性和方法
    
    /**
      * 父类  BigDataEngineer
      *   不可变 name
      *   可变 age
      *   方法 study
      * 子类  HadoopEngineer
      *
      */
    class BigDataEngineer{
      val  name="BigData"
      var age=10
      def study():Unit={
        println("学习和开发")
      }
    }
    class HadoopEngineer extends BigDataEngineer{
      //子类覆盖父类中的study方法  override
      override def study(): Unit = {
        age=12
        super.study()
        println("开发hadoop")
      }
    }
    object Scala_08_extends extends App{
         val engineer = new HadoopEngineer
         println(engineer.name)
         engineer.study()
    }
    问题:子类在创建对象的时候,是否调用了父类的构造器? 
    	scala中子类创建对象的时候也同样调用了父类的构造器
    
    
  • Scala中构造机制

    • /**
        * 类 Person_09
        * 子类 Sun_09
        */
      class Person_09{
        println("Person_09")  //主构造器调用完成之后直接调用
      }
      
      class Sun_09 extends  Person_09{
        println("Sun_09")
      }
      
      object Scala_09_extends extends  App {
         val sun_0 = new Sun_09
         //根据打印结果
          //在子类创建对象的过程中,调用了父类的构造器的
      }
      
2.9 子类调用父类的构造器
  • 子类主构造器没有参数,父类主构造器有参数
    子类主构造器有参数,父类主构造器也有参数
    
    /**
      * 父类PC 电脑(cup memory)
      *   子类 NotePC
      *    台式机:DeskPC(cup memory)
      */
    class PC(val cpu:Int,val memory:Int)
    
    class NotePC extends PC(cpu = 10,memory = 20)
    
    class DeskPC(cpu:Int,memory:Int) extends PC(cpu,memory)
    
    object Scala_10_extends {
      def main(args: Array[String]): Unit = {
        val n = new NotePC
        println(n.cpu)
        println(n.memory)
        println("----------------------")
        val deskPC=new DeskPC(30,60)
        println(deskPC.cpu)
        println(deskPC.memory)
      }
    }
    
2.10 抽象类
  • 定义: abstract class 类名
    1.可以定义抽象方法和抽象属性(没有初始化的属性)
    2.可以有非抽象的方法和非抽象属性
    3.如果方法或者属性被final修饰,不能够被重写
    
    /**
      * Employee 员工
      * val name 抽象
      * var age 非抽象的
      * 抽象方法 work
      * 非抽象方法 study
      * final 方法:sleep
      */
    abstract class Employee {
      val name: String //抽象属性 数据类型不能够省略
      var age = 25
    
      def work(): Unit //抽象方法返回值类型不能够省略
      def study(): Unit = {
        println("学习公司文化")
      }
    
      final def sleep(): Unit = {
        println("休息")
      }
    }
    
    class ScalaEmployee extends Employee {
      /**
        * override  如果覆盖的是非抽象的方法或者属性 这里不能够省略
        * 如果覆盖的是抽象方法或者属性 这里可以省略
        */
      override val name: String = "scala"
    
      override def work(): Unit = {
        println("开发scala应用程序")
      }
    
    }
    
    object Scala_11_extends extends App {
      private val employee = new ScalaEmployee
      println(employee.name)
      employee.work()
      employee.study()
    }
    
2.11匿名内部类
  • 应用场景:
    	ScalaProgramer  只会开发scala应用程序。python 
    
    class ScalaProgrammer {
      def workerByScala(): Unit = {
        println("开发scala应用程序")
      }
    }
    class pyAndScaProgrammer extends ScalaProgrammer{
        def workerByPython(): Unit = {
            println("学习并开发python")
          }
    }
    object Scala_12_innerclass {
      def main(args: Array[String]): Unit = {
        //python项目 临时性需求
       val scala= new ScalaProgrammer {
          def workerByPython(): Unit = {
            println("学习并开发python")
          }
        }
        scala.workerByPython()
        scala.workerByScala()
        println(scala.getClass)
      }
    }
    
2.12 超级父类
  • Any 超级分类
    	AnyRef  所有引用类型对象的超级父类 ScalaProgrammer
    	AnyVal  所有值类型对象的超级父类 Int Double...
    
2.13 类型转换和类型判断
  • 子类继承父类,父类的引用可以指向子类对象。父类的引用是多态的。多态的问题 :类型转换异常
    
    *  val worker = w.asInstanceOf[Worker]
    	1. 对象.isInstanceOf[类型]  模糊判断 不精准
          * 2. 对象.getClass=classOf[类型]
    class Worker {
      def work(): Unit = {
        println("工作")
      }
    }
    
    class JavaWorker extends Worker {
      def workByJava(): Unit = {
        println("开发java项目")
      }
    }
    
    object Scala_13_change {
      def boss(w: Any): Unit = {
        //将any对象转换成 worker对象
        //判断对象的类型
        /**
          * 1. 对象.isInstanceOf[类型]  模糊判断 不精准
          * 2. 对象.getClass=classOf[类型]
          */
        if (w.isInstanceOf[Worker]) {
          val worker = w.asInstanceOf[Worker]
          worker.work()
        } else {
          println("回家等消息")
        }
      }
    
      def boss2(w: Any): Unit = {
        //将any对象转换成 worker对象
        //判断对象的类型
        /**
          * 1. 对象.isInstanceOf[类型]  模糊判断 不精准
          * 2. 对象.getClass=classOf[类型]
          */
        if (w.getClass()==classOf[JavaWorker]) {
          val worker = w.asInstanceOf[JavaWorker]
          worker.workByJava()
        } else {
          println("回家等消息")
        }
      }
    
      def main(args: Array[String]): Unit = {
        val worker = new Worker
        /*boss(worker)
        boss(new Student)*/
        val javaWorker = new JavaWorker
        boss2(worker)
      }
    }
    
2.14特质
  • 特质的功能

    • 格式:trait 名称
    • 功能:
      • 特质可以作为java中的接口使用
      • 特质可以作为抽象类使用
      • 特质可以扩展对象的方法(1 个方法 --》多个方法)
      • 特质可以扩展特定方法的功能
  • 特质作为接口使用

    • /**
        * 定义
        * trait  名称
        * 可以作为接口使用
        *   1.可以定抽象方法
        *   2.接口可以多实现
        */
      格式:类 extends Tarit名称 with  Tarit名称2 with Tarit名称3
      
      trait HelloTrait {
        def sayHellByChina(): Unit
      }
      
      trait HelloTraitHanguo {
        def sayHellByHanguo(): Unit
      }
      
      trait HelloTraitTaiguo {
        def sayHellByTaiguo(): Unit
      }
      
      class HelloTraitImpl extends HelloTrait with HelloTraitHanguo with HelloTraitTaiguo {
        override def sayHellByChina(): Unit = {
          println("你好")
        }
      
        override def sayHellByHanguo(): Unit = {
          println("阿尼哈沙有")
        }
      
        override def sayHellByTaiguo(): Unit = {
          println("萨瓦迪卡")
        }
      }
      
      object Scala_14_trait {
        def main(args: Array[String]): Unit = {
          val impl = new HelloTraitImpl
          impl.sayHellByChina()
          impl.sayHellByHanguo()
          impl.sayHellByTaiguo()
        }
      }
      
  • 特质作为抽象类使用

    • trait AbstractTrait {
        //非抽象属性和方法
        val name = "itcast"
      
        def study(): Unit = {
          println("学习")
        }
      
        //抽象属性和方法
        val age: Int
      
        def work(): Unit
      
      }
      
      class AbstractTraitImpl extends AbstractTrait {
        override val age: Int = 10
      
        override def work(): Unit = {
          println("工作")
        }
      }
      
      object Scala_15_trait extends App {
        private val impl = new AbstractTraitImpl
        println(impl.age)
        println(impl.name)
        impl.work()
        impl.study()
      }
      特质和抽象类的区别
      	1.抽象类可以有自己的主构造器以及初始化参数
          2.特质可以多实现但是抽象类只能进行单继承或者多重继承
      
  • 特质扩展对象的功能

    • package cn.itcast.day02
      
      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_16_trait {
        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()
        }
      }
      
  • 特质扩展特定方法的功能

    • super: 线性调用的标志符,线性是动态过程 是根据特质的混入顺序有关的
      线性执行顺序:自右向左的过程
      
      class Tank2 {
        def shoot(): Unit = {
          println("发射")
        }
      }
      
      trait Aim2 extends Tank2 {
        override def shoot(): Unit = {
      
          println("瞄准")
          super.shoot()
        }
      }
      
      trait Scan2 extends Tank2 {
        override def shoot(): Unit = {
          println("扫描")
          super.shoot()
        }
      }
      class SuperTank extends Tank2 with Aim2 with Scan2
      
      object Scala_17_trait {
        def main(args: Array[String]): Unit = {
          val tank = new SuperTank
          tank.shoot()
        }
      }
      
  • 特质构造机制

    • 构造机制的执行原则:  从左往右  自上而下
      
      trait T0{
        println(0)
      }
      trait T1{
        println(1)
      }
      trait T2{
        println(2)
      }
      trait T3 extends T1{
        println(3)
      }
      class Timpl extends T0 with T3 with  T2 with  T1{
        println("Timpl")
      }
      
      object Scala_18_trait extends App {
        //1 2 1 3 0
        // Timpl  1 2 1 3 0
        new Timpl  // 从左往右  自上而下
      }
      

3. 模式匹配

  • 功能类似于java中switch结构,但是要比swith强大的多

    • 数值
    • 数据类型
    • Array
    • List
    • Tuple
    • Map
    • 自定义数据类型
  • 结构:
    	value match {
            case 需要匹配值或者类型 =>{ 执行逻辑}
            case _ => {执行逻辑} //默认的匹配
        }
    
  • 模式匹配值匹配

    • //值匹配
      val arr = Array("hadoop", "scala", "spark")
      var value = arr((math.random * arr.size).toInt)
      //println("value:" + value)
      value="java"
      
      /**
        * value match {
        * case 需要匹配值或者类型 =>{ 执行逻辑}
        * case _ => {执行逻辑} //默认的匹配
        * }
        */
      value match {
        case "hadoop" => println("匹配Hadoop")
        case "scala" => println("匹配scala")
        case "spark" => println("匹配spark")
        case _ =>println("默认匹配")
      }
      
  • 数据类型匹配

    • object DataType {
        def main(args: Array[String]): Unit = {
          val arr=Array("hadoop",1.34,10,true)
          var value = arr((math.random * arr.size).toInt)
          println("value:"+value)
          value match {
            case s:String => println(s+"-------------")
            case d:Double => println(d+"-------------")
            case i:Int => println(i+"-------------")
            case b:Boolean =>println(b+"-------------------")
          }
        }
      }
      
  • 模式匹配数组

    • object MatchArray{
        def main(args: Array[String]): Unit = {
          val arr=Array("hadoop",1.34,10,true)
          arr match {
             //能否有个配所有array
            
            //非精确匹配
            case Array("hadoop1",_*) =>println("333333")
            //占位符匹配
            case Array("hadoop",1.34,_,_) =>println("222222222")
             //精确匹配
            case Array("hadoop",1.34,10,true) =>println("111111")
              case Array(_*) =>println("4444444")
          }
        }
      }
      
  • 模式匹配列表

    • object MatchList{
        def main(args: Array[String]): Unit = {
          val list=List("hadoop","spark","scala")
          list match {
            case "hadoop"::"spark"::"scala"::Nil =>println("sfsfsfdsfsdsdfd")
             //模糊匹配
            case List(x,_*) =>println(x)
            case List(x,y,_) =>println(x+"\t"+y)
            //精确匹配
            case List(x,y,z) =>println(x+"\t"+y+"\t"+z)
            case List("hadoop","spark","scala") => println("精确匹配list")
          }
        }
      }
      
  • 模式匹配Tuple

    • object MatchTuple {
        def main(args: Array[String]): Unit = {
          val t = ("hadoop", 1.23, 10, true)
      
          t match {
            case (x,_,_,_) =>println("sdfdsfds")
            case _ =>println("默认匹配。。。。")
            //case ("hadoop",_*) =>println("")
            case ("hadoop",_,_,_) =>println("匹配占位符tuple")
            case  ("hadoop", 1.23, 10, true) =>println("精确匹配tuple")
          }
      
        }
      }
      
  • 模式匹配Map

    • object  MatchMap{
        def main(args: Array[String]): Unit = {
          val map=Map("hadoop"->100,"scala"->50)
          val value=map.get("java")
          value match  {
            case Some(x) =>println(x)
            case None =>println("没有值")
          }
        }
      }
      
  • 模式匹配自定数据类型

    • 样例类 case class 名称

      • 样例类跟普通类区别:样例类能够自动构建apply方法
    • 样例对象

      • case object 名称 :应用场景 只是作为标志
    • case class Task(name: String)
      case object TaskObject
      
      object MatchCaseClass {
        def main(args: Array[String]): Unit = {
          val arr = Array(Task("itcast"), TaskObject)
          val value = arr((math.random * arr.size).toInt)
          println("value:" + value)
          Task("lisi") match {
            case Task(name) => println("name:" + name)
            case TaskObject => println("匹配样例对象")
          }
        }
      }
      

4. 偏函数 x=>y

  • 把模式匹配这种形式 放在一个方法或者一个函数中,就构成一种新的函数,偏函数
    //方法
    def 名称(参数)= value math{
        case 操作
    }
    //函数
    val 名称:PartialFunction[输入数据类型,返回值数据类型] ={
        case 操作
    }
    
    object Scala_20_pianhanshu {
    
      def intMatch(x: Int) = x match {
        case 10 => println("10")
        case 100 => 100
      }
     
      def main(args: Array[String]): Unit = {
        intMatch(10)
        println(intMatch(100))
    
        val matchFuncion: PartialFunction[Int, String] = {
          case x:Int => x + " is even"
        }
        println(matchFuncion(10))
      }
    }
    
    

5.逆变协变非变

  • class Apple
    class RedApple  extends Apple
    class Box[T]
    问题:RedApple 是 Apple 子类, Box[RedApple] 是不是 Box[Apple]子类? 假如  Box[RedApple] 是 Box[Apple]子类
     val box:Box[Apple] =new Box[RedApple] 则成立 ,反之则不成立  
    答案 :以上假设不成立
    
    要想让以上操作成立 需要协变操作
    
    
    
    
    RedApple extends Apple
    class Box[T]  
    a=Box[Apple]  b=Box[RedApple]
    
    
    class Box[+T]  
    a=Box[Apple]  b=Box[RedApple]
    
    class Box[-T]  
    a=Box[Apple]  b=Box[RedApple]
    逆变:class Box[-T]  
    	val box:Box[RedApple] =new Box[Apple] 
    
    
    class RedApple extends Apple
    
    class Box[+T]  //协变
    
    class Box2[-T]
    
    object Scala_21_fanxin {
      def main(args: Array[String]): Unit = {
        val box: Box[Apple] = new Box[RedApple]
    
        val box2:Box2[RedApple] =new Box2[Apple]
      }
    }
    Son extends Person
    
    总结:a=ArrayList<Person> b=ArrayList<Son>
        
    C[T]:	A是B的子类 C[A]与C[B]之间没有任何关系  非变操作
    C[+T]: A是B的子类  C[A]是C[B]的子类  协变操作
    C[-T]: A是B的子类  C[A]是C[B]的父类  逆变操作
    

6.上下界

  • 上下界 影响的是方法的入参
    
    U>:Class U 带表的class本身以及其父类 下界操作 下界限制不住
    U<:Class U 代表class 本身以及其子类  上界操作
    
    class OldMan extends Man
    
    class  OldOldMan extends  OldMan
    
    class YoungMan extends Man
    
    class ChildMan extends YoungMan
    
    class Sport {
      //添加下界操作 U 代表的是 OldMan 本身 或者是其父类  下界操作 其实是无下界
      def guangchangwu[U >: OldMan](man: U): Unit = {
        println("广场舞")
      }
      //U 带表示 YoungMan本身以及其子类
      def qiaodaima[U<:YoungMan](man: U): Unit = {
        println("敲代码")
      }
    }
    
    object Scala_22_upanddown {
      def main(args: Array[String]): Unit = {
        val sport = new Sport
        val yman = new YoungMan
        val oman = new OldMan
        val ooman=new OldOldMan
        val cman = new ChildMan
     /*   sport.guangchangwu(yman)
        sport.guangchangwu(oman)
        sport.guangchangwu(ooman)*/
    
        sport.qiaodaima(cman)
    
      }
    }
    
    

7.Scala并发操作

  • 格式:	
    	class 线程类 extends Actor{
            def act()
        }
    //启动线程
    	actor.start()
    
    /**
      * 创建线程类 MyActor
      */
    class MyActor(val name: String) extends Actor {
      override def act(): Unit = {
        for (i <- 0 to 10) {
          println(name + ":" + i)
        }
      }
    }
    
    object Scala_23_actor {
      def main(args: Array[String]): Unit = {
        val itcast = new MyActor("itcast")
        val tian = new MyActor("Tian")
        itcast.start()
        tian.start()
      }
    }
    
  • Actor基于消息机制的并发

    • actor能够发送消息 和接受消息,根据消息的不同,去执行不同的业务逻辑

    • ! 发送消息

    • class MyActor2 extends Actor {
        override def act(): Unit = {
          var flag = true
          while (flag)
            receive { //阻塞
              case "start" => println("启动成功") //执行逻辑完成后自动退出
              case "test" => println("测试")
              case "end" => {
                println("退出")
                flag = false
              }
            }
        }
      }
      
      object Scala_24_actor {
        def main(args: Array[String]): Unit = {
          val actor = new MyActor2()
          actor.start()
          actor ! "start"
          actor!"test"
          actor ! "end"
        }
      }
      
  • loop react

    • class MyActor2 extends Actor {
        override def act(): Unit = {
          loop{
            react{
              case "start"=>println("启动成功过")
              case "test" =>println("测试")
              case "end"=> exit()
            }
          }
        }
      }
      
      object Scala_24_actor {
        def main(args: Array[String]): Unit = {
          val actor = new MyActor2()
          actor.start()
          actor ! "start"
          actor!"test"
          actor ! "end"
        }
      }
      
  • Actor发送消息的三种方式

    • ! 异步消息 并且无返回值

    • !? 同步消息 有返回值

    • !! 异步消息 有返回值 Future[Any]

    • 同步消息和异步消息

      • 同步消息:发送消息后,会等待消息执行逻辑完成,再返回
      • 异步消息:发送消息后直接返回,返回会在将来的某一时刻返回 Future[Any]
    • 总和案例:

      • 结合样例类方式 来整同步消息和异步消息以及返回值
      • 需要构建3个样例类
    • /**
        * 消息模型
        * 同步消息
        * 异步消息
        * 返回值消息
        */
      case class SynMsg(msg: String, time: Long)
      
      case class AsynMsg(msg: String, time: Long)
      
      case class ReplayMsg(msg: String)
      
      class MsgActor extends Actor {
        override def act(): Unit = {
          loop {
            react {
              case SynMsg(msg, time) => {
                Thread.sleep(time)
                println(msg)
                sender ! ReplayMsg(msg + "---SynMsg-----")
              }
              case AsynMsg(msg, time) => {
                Thread.sleep(time)
                println(msg)
                sender ! ReplayMsg(msg + "---AsynMsg-----")
              }
            }
          }
        }
      }
      
      object Scala_25_actor {
        def main(args: Array[String]): Unit = {
          val actor = new MsgActor
          actor.start()
          /*val msg1=actor!?SynMsg("itcast",5000)
          val msg2=actor!?SynMsg("itcast2",1000)
           println(msg1)
           println(msg2)*/
      
          val msg1 = actor !! AsynMsg("itcast", 5000)
          val msg2 = actor !! AsynMsg("itcast2", 1000)
      
          val list = ListBuffer[Future[Any]]()
          list += msg1
          list += msg2
      
          while (list.size > 0) {
            for (msg <- list) { //msg:Future[Any]
              //判断future是否接收到数据
              if (msg.isSet) { //ture 代表已经接受到数据
                val replayMsg = msg.apply().asInstanceOf[ReplayMsg]
                println(replayMsg.msg)
                list -= msg
              }
            }
          }
        }
      }
      
  • 基于Actor的wordcount案例

    • 操作步骤:

      • 准备文件 a.txt b.txt c.txt
      • 构建actor
      • 通过样例类 构建消息的载体 case FilePathMsg(path:String)
      • actor接受消息 并且处理文件数据
      • 接受返回值 并且将返回值放在ListBuffer进行管理
      • 对ListBuffer进行循环操作,拿到文件处理数据,把文件处理数据放在一个集合中
      • 对集合进行汇总处理
    • package cn.itcast.day02
      
      import java.io.File
      
      import scala.actors.{Actor, Future}
      import scala.collection.mutable.{ArrayBuffer, ListBuffer}
      import scala.io.Source
      
      /**
        * 样例类方式构建消息载体
        */
      case class FilePathMsg(path: String)
      
      //返回值消息
      case class FileResultMsg(result: Map[String, Int])
      
      class FileActor extends Actor {
        override def act(): Unit = {
          loop {
            react {
              case FilePathMsg(path) => {
                //读取文件数据 并且进行处理 Map
                val map: Map[String, Int] = Source.fromFile(new File(path)).getLines().mkString(",").split(",")
                  .map((x: String) => (x, 1)).groupBy((t: Tuple2[String, Int]) => t._1)
                  .mapValues((arr: Array[Tuple2[String, Int]]) => arr.length)
                sender ! FileResultMsg(map)
              }
            }
          }
        }
      }
      
      object Scala_26_wordcount {
        def main(args: Array[String]): Unit = {
          val arr = Array("d:/a.txt", "d:/b.txt", "d:/c.txt")
          val list = ListBuffer[Future[Any]]()
          //数组封装了每个文件处理好的数据
          val fileDataArray = ArrayBuffer[Map[String, Int]]()
      
          for (path <- arr) {
            val actor = new FileActor
            actor.start()
            //发送异步消息 并且接受到每个文件的处理结果
            val result = actor !! FilePathMsg(path)
            list += result
          }
      
          while (list.size > 0) {
            for (f <- list if f.isSet) {
              val fileResult = f.apply().asInstanceOf[FileResultMsg]
              fileDataArray += fileResult.result
              list -= f
            }
          }
          val wordcount = fileDataArray.flatten.groupBy((t: Tuple2[String, Int]) => t._1)
            .mapValues((arr: ArrayBuffer[Tuple2[String, Int]]) => {
              arr.map((t: Tuple2[String, Int]) => t._2).sum
            })
          println(wordcount)
        }
      }
      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值