scala相关操作(四)

  1. 模式匹配

34.1 简单模式匹配

package com.ithe.scala

import scala.io.StdIn

/**
* 34.1 简单模式匹配
* 示例
* 需求说明
* 1.	从控制台输入一个单词(使用StdIn.readLine方法)
* 2.	判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
* 3.	打印这句话
* 单词	      返回
* hadoop	    大数据分布式存储和计算框架
* zookeeper	大数据分布式协调服务框架
* spark	    大数据分布式内存计算框架
* 未匹配	      未匹配
*/
object Demo34_1 {
 def main(args: Array[String]): Unit = {
   var word:String = ""
   while(true){
     println("请输入单词,按回车确认。")
     word = StdIn.readLine()
     word match{
       case "hadoop" => println("大数据分布式存储和计算框架")
       case "zookeeper" => println("大数据分布式协调服务框架")
       case "spark" => println("大数据分布式内存计算框架")
       case "exit" => System.exit(0)
       case _ => println("未匹配")
     }
   }
 }

}

34.2 匹配类型

package com.ithe.scala

/**
* 34.2 匹配类型
* 示例
* 需求说明
* 1	定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
* 2	定义模式匹配,然后分别打印类型的名称
*/
object Demo34_2 {
 def main(args: Array[String]): Unit = {
   // 1	定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
   val a :Any="hadoop"
   // 2	定义模式匹配,然后分别打印类型的名称
   val a_type: String = a match {
     case _:String => "String"
     case _:Int => "Int"
     case _:Double => "Double"
     case _ => "Any"
   }
   println(a_type)
 }
}

34.3 守卫

package com.ithe.scala

import scala.io.StdIn

/**
* 34.3 守卫
* 示例
* 需求说明
* 1	从控制台读入一个数字a(使用StdIn.readInt)
* 2	如果 a >= 0 而且 a <= 3,打印[0-3]
* 3	如果 a >= 4 而且 a <= 8,打印[4,8]
* 4	否则,打印未匹配
*/
object Demo34_3 {
 def main(args: Array[String]): Unit = {
   val a = StdIn.readInt()
   a match {
     case _ if (a >= 0 && a <= 3) => println("[0-3]")
     case _ if (a >= 4 && a <= 8) => println("[4-8]")
     case _ => println("未匹配")
   }
 }
}

34.4 匹配样例类

package com.ithe.scala

/**
* 34.4 匹配样例类
* 示例
* 需求说明
* 1	创建两个样例类Customer、Order
* Customer包含姓名、年龄字段
* Order包含id字段
* 2	分别定义两个样例类的对象,并指定为Any类型,(必须声明类型,否则会报错。)
* 3	使用模式匹配这两个对象,并分别打印它们的成员变量值
*/
object Demo34_4 {
 //1	创建两个样例类Customer、Order
 // Customer包含姓名、年龄字段
 // Order包含id字段
 case class Customer(name:String,age:Int)
 case class Order(id:Int)
 //2	分别定义两个样例类的对象,并指定为Any类型,(必须声明类型,否则会报错。)
 //3	使用模式匹配这两个对象,并分别打印它们的成员变量值
 def main(args: Array[String]): Unit = {
   val a:Any = Customer("zhangsan",20)
   val b:Any = Order(1)
   b match {
     case Customer(name,age) => println(name,age)
     case Order(id) => println(id)
     case _ => println("未匹配")
   }
 }
}

34.5 匹配集合

/**

**/

34.6 匹配数组

package com.ithe.scala

/**
* 34.6 匹配数组
* 示例说明
* 1	依次修改代码定义以下三个数组
* Array(1,x,y)   // 以1开头,后续的两个元素不固定
* Array(0)       // 只匹配一个0元素的元素
* Array(0, ...)  // 可以任意数量,但是以0开头
* 2	使用模式匹配上述数组
*
*/
object Demo34_6 {
 def main(args: Array[String]): Unit = {
   var a = Array(1,2,3)
   a = Array(0)
   a = Array(3,4,5,6,7)
   a match{
     case Array(1,x,y)=>println(s"1 and other 2 elements: $x,$y")
     case Array(0) => println("only 0")
     case Array(0,_*)=>println( "0 and others ")
     case _ => println("其他")
   }

 }
}

34.7 匹配列表

package com.ithe.scala

/**
* 34.7 匹配列表
* 示例说明
* 1	依次修改代码定义以下三个列表
* List(0)             // 只保存0一个元素的列表
* List(0,...)         // 以0开头的列表,数量不固定
* List(x,y)           // 只包含两个元素的列表
* 2	使用模式匹配上述列表
*/
object Demo34_7 {
 //  1	依次修改代码定义以下三个列表
 //  List(0)             // 只保存0一个元素的列表
 //  List(0,...)         // 以0开头的列表,数量不固定
 //  List(x,y)           // 只包含两个元素的列表
 //  2	使用模式匹配上述列表
 def main(args: Array[String]): Unit = {
   var a = List(0)
   //a = List(0,1,2)
   //a = List(6,7)
   //写法一
   print("写法一,")
   a match {
     case List(0) => println("只保存0一个元素的列表")
     case List(0, _*) => println("以0开头的列表,数量不固定")
     case List(x, y) => println("只包含两个元素的列表")
     case _ => println("其他")
   }

   //写法二
   print("写法二,")
   a match {
     case 0::Nil=>println("只保存0一个元素的列表")
     case 0::tail => println("以0开头的列表,数量不固定")
     case x::y::Nil => println("只包含两个元素的列表")
     case _ => println("其他")
   }
 }
}

34.8 匹配元组

package com.ithe.scala

/**
* 34.8 匹配元组
* 示例说明
* 1	依次修改代码定义以下两个元组
* (1, x, y)       // 以1开头的、一共三个元素的元组
* (x, y, 5)   // 一共有三个元素,最后一个元素为5的元组
* 2	使用模式匹配上述元素
*/
object Demo34_8 {
 def main(args: Array[String]): Unit = {
   var a = (1,2,3)
   a = (2,3,5)
   a match{
     case (1,x,y) => println("以1开头的、一共三个元素的元组")
     case (x,y,5) => println("一共有三个元素,最后一个元素为5的元组")
     case _ => println("其他")
   }
 }
}

34.9 变量声明中的模式匹配

34.9.1 示例 | 获取数组中的元素

package com.ithe.scala

/**
* 34.9.1 示例 | 获取数组中的元素
* 需求说明
* 生成包含0-10数字的数组,使用模式匹配分别获取第二个、第三个、第四个元素
*/
object Demo34_9_1 {
 def main(args: Array[String]): Unit = {
   //1 生成包含0-10数字的数组,
   val arr = (1 to 10).toArray

   //2 使用模式匹配分别获取第二个、第三个、第四个元素
   //思路一
   val Array(a, b, c, d, e, f, g, h, i, j) = arr
   //思路二
   val Array(_, x, y, z, _*) = arr

   println(b, c, d)
   println(x, y, z)
 }
}

34.9.2 示例 | 获取List中的数据

package com.ithe.scala

/**
* 34.9.2 示例 | 获取List中的数据
* 需求说明
* 	生成包含0-10数字的列表,使用模式匹配分别获取第一个、第二个元素
*/
object Demo34_9_2 {
 def main(args: Array[String]): Unit = {
   //1生成包含0-10数字的列表
   val list = (1 to 10).toList
   //2 使用模式匹配分别获取第一个、第二个元素
   //思路一
   val List(a,b,_*)= list
   //思路二
   val x::y::tail=list

   println(a,b)
   println(x,y)
 }
}

  1. Option类型
package com.ithe.scala

/**
* 35. Option类型
* 示例一
* 示例说明
* 1	定义一个两个数相除的方法,使用Option类型来封装结果
* 2	然后使用模式匹配来打印结果
*   不是除零,打印结果
*   除零打印异常错误
*
* 示例二
* 示例说明
* 	重写上述案例,使用getOrElse方法,当除零时,或者默认值为0
*/
object Demo35_1and2 {
 // 1	定义一个两个数相除的方法,使用Option类型来封装结果
 def div(a:Double,b:Double)={
   if(b!=0){
     Some(a/b)
   }else{
     None
   }
 }
 // 2	然后使用模式匹配来打印结果
 //  不是除零,打印结果
 //  除零打印异常错误
 def main(args: Array[String]): Unit = {
   val c = div(1,0)
   //示例一
   c match {
     case Some(x) => println("结果为"+x)
     case None => println("除数为零")
   }

   //示例二
   println(c.getOrElse(0))

 }
}

  1. 偏函数
package com.ithe.scala

/**
* 36. 偏函数
* 示例一
* 示例说明
* 定义一个偏函数,根据以下方式返回
* 输入	返回值
* 1	  一
* 2	  二
* 3	  三
* 其他	其他
*/
object Demo36_1 {

 val func: PartialFunction[Int,String] ={
   case 1 => "一"
   case 2 => "二"
   case 3 => "三"
   case _ => "其他"
 }

 def main(args: Array[String]): Unit = {
   val result=func(1)
   println(result)
 }
}

package com.ithe.scala

/**
*36. 偏函数
* 示例二
* 示例说明
* 1	定义一个列表,包含1-10的数字
* 2	请将1-3的数字都转换为[1-3]
* 3	请将4-8的数字都转换为[4-8]
* 4	将其他的数字转换为(8-*]
*/
object Demo36_2 {
def main(args: Array[String]): Unit = {
  val list = (1 to 10).toList
  val list2 = list.map {
    case x if (x >= 1 && x <= 3) => "[1-3]"
    case x if (x >= 4 && x <= 8) => "[4-8]"
    case x if (x > 8) => "(8-*]"
    case _ => "其他"
  }
  println(list2)


}
}

  1. 正则表达式
package com.ithe.scala

import scala.util.matching.Regex

/**
* 37. 正则表达式
*/
object Demo37_1and2and3 {

 def main(args: Array[String]): Unit = {
   // 示例一
   // 示例说明
   //   1	定义一个正则表达式,来匹配邮箱是否合法
   //   2	合法邮箱测试:qq12344@163.com
   //   3	不合法邮箱测试:qq12344@.com
   println("示例一:")
   val regex = """.+@.+\..+""".r
   val email1 = "qq12344@163.com"
   val email2 = "qq12344@.com"
   val matches: Iterator[Regex.Match] = regex.findAllMatchIn(email1)
   if (matches.toList.size > 0) {
     println(email1+"邮箱合法")
   }else println(email1+"邮箱不合法")

   if (regex.findAllMatchIn(email2).size > 0) {
     println(email2+"邮箱合法")
   }else println(email2+"邮箱不合法")

   //示例二
   //找出以下列表中的所有不合法的邮箱
   //"38123845@qq.com", "a1da88123f@apache.org", "zhansan@163.com", "123afadff.com"
   println("我是分割线"+"-"*15+"\n示例二:")
   val list  = List("38123845@qq.com", "a1da88123f@apache.org", "zhansan@163.com", "123afadff.com")
   val list2 = list.filter(x=> regex.findAllMatchIn(x).isEmpty)
   println(list2)

   //示例三
   // 示例说明
   // 1	有以下邮箱列表
   // "38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com"
   // 2	使用正则表达式进行模式匹配,匹配出来邮箱运营商的名字。例如:邮箱zhansan@163.com,需要将163匹配出来
   // 使用括号来匹配分组
   // 3	打印匹配到的邮箱以及运营商
   println("我是分割线"+"-"*15+"\n示例三:")
   //下面2个括号,表示2个分组。
   val regex2 = """.+@(.+)\.(.+)""".r
   val list3 = list.map(x => {
     x match {
       //注意,下面的@跟邮箱没半毛钱关系。是固定语法需要。将符合正则表达式的两个分组的值用两个变量接收
       case x@regex2(company,tail) => s"$x 公司是$company 后缀是$tail"
       case x => x + " 未知"
     }
   })
   list3.foreach(println(_))

 }
}

  1. 异常处理
    38.1 捕获异常
/**
合在【38.2 抛出异常】一起了。
**/

38.2 抛出异常

package com.ithe.scala

/**
* 38. 异常处理
* 38.1 捕获异常
* 示例
* 使用try..catch来捕获除零异常
*
* 38.2 抛出异常
* 示例
* 在main方法中抛出一个异常
*/
object Demo38_1and2 {
 def main(args: Array[String]): Unit = {
   try {
     val a = 3 / 0
     println("如果上面一句存在异常,那么这句代码不会执行,否则会执行")
   } catch {
     case e: Exception => {
       println("1如果捕捉到异常,这句代码就会执行")
       e.printStackTrace()
     }
   } finally {
     println("2这句代码一定会执行")
   }
   println("3因为上面的异常被合理处理,所以这句代码会继续执行")
   throw new Exception("4对方不想理你,并向你抛出了一个异常")
   println("由于上面抛了异常,所以这句代码永远不会执行")
 }
}

  1. 提取器(Extractor)
    39.1 定义提取器
package com.ithe.scala

/**
* 39. 提取器(Extractor)
* 39.1 定义提取器
* 示例
* 示例说明
* 1	创建一个Student类,包含姓名年龄两个字段
* 2	定义半生对象,重写unapply方法,实现一个类的解构器,并使用match表达式进行模式匹配,提取类中的字段。
*/
object Demo39 {
 //1	创建一个Student类,包含姓名年龄两个字段
 class Student(var name:String,var age:Int)
 //2	定义半生对象,重写unapply方法,实现一个类的解构器
 object Student{
   def unapply(arg: Student): Option[(String, Int)] = {
     if(arg!=null) Some(arg.name,arg.age)
     else None
   }
 }

 def main(args: Array[String]): Unit = {
   // 思考,下面是用new的方式创建的Student对象,如果不想用new关键字,还需做什么才行?
   // 答案:在object中重写apply()方法,或者将Student定义为样例类case class
   // 总结,重写apply可以免new创建对象,重写unapply后才可以用作模式匹配。
   val stu = new Student("张三",20)
   //使用match表达式进行模式匹配,提取类中的字段。
   stu match {
     case Student(name,age) => println(name,age)
     case _ => println("未匹配")
   }
 }
}

  1. 泛型
    40.1 定义一个泛型方法
package com.ithe.scala

/**
* 40. 泛型
* 40.1 定义一个泛型方法
* 示例
* 示例说明
* 定义一个方法来获取任意类型数组的中间的元素
* 定义一个方法getMiddle1(),不用泛型直接实现(基于Array[Int]实现)。缺点是集合的元素类型只能局限是Int
* 再定义一个方法getMiddle2[T](),加入泛型支持。优点是,支持所有数据类型,在运行时才指定数据类型。
*/
object Demo40_1 {
 //  定义一个方法getMiddle1(),不用泛型直接实现(基于Array[Int]实现)。缺点是集合的元素类型只能局限是Int
 def getMiddle1(arr:Array[Int])=arr(arr.length/2)
 //再定义一个方法getMiddle2[T](),加入泛型支持。优点是,支持所有数据类型,在运行时才指定数据类型。
 //如何理解,第一个T是指定泛型,第二个T是引用第一个T。
 def getMiddle2[T](arr:Array[T])=arr(arr.length/2)

 def main(args: Array[String]): Unit = {
   getMiddle1(Array(1,2,3,4,5))
   getMiddle2[String](Array("a","b","c","d","e"))
   //因为Scala编译器可以自动推断类型,所以上面的[String]可以省略,变成如下
   getMiddle2(Array("a","b","c","d","e"))
 }
}

40.2 泛型类

package com.ithe.scala

/**
* 40.2 泛型类
* 示例
* 示例说明
* 1	定义一个Pair泛型类
* 2	Pair类包含两个字段,而且两个字段的类型不固定
* 3	创建不同类型泛型类对象,并打印
*/
object Demo40_2 {
 // 1	定义一个Pair泛型类
 // 2	Pair类包含两个字段,而且两个字段的类型不固定
 class Pair[T](attr1:T,attr2:T){
   println(attr1,attr2)
 }
 // 3	创建不同类型泛型类对象,并打印
 def main(args: Array[String]): Unit = {
   val a = new Pair[Int](1,2)
   val b = new Pair[String]("a","b")
   //下面这句为什么一个是Int,一个是String,因为,编译器判定都是Any类型,等价于new Pair[Any](1,"b")
   val c = new Pair(1,"b")
 }
}

40.3 上下界
40.3.1 上界定义

package com.ithe.scala

/**
* 40.3 上下界
* 40.3.1 上界定义
* 示例
* 示例说明
* 1	定义一个Person类
* 2	定义一个Student类,继承Person类
* 3	定义一个demo泛型方法,该方法接收一个Array参数,
* 4	限定demo方法的Array元素类型只能是Person或者Person的子类
* 5	测试调用demo,传入不同元素类型的Array
*/
object Demo40_3_1 {

 //  1	定义一个Person类
 class Person

 //  2	定义一个Student类,继承Person类
 class Student extends Person

 //  3	定义一个demo泛型方法,该方法接收一个Array参数,
 //  4	限定demo方法的Array元素类型只能是Person或者Person的子类
 def demo[T <: Person](arr: Array[T]) = arr.foreach(println(_))

 //  5	测试调用demo,传入不同元素类型的Array
 def main(args: Array[String]): Unit = {
   demo(Array(new Person, new Person, new Student, new Student))
   //编译报错,因为"hadoop"是String类,不是Person的子类
   //demo("hadoop")
 }
}

40.3.2 下界

package com.ithe.scala

/**
* 40.3.2 下界
* 示例
* 示例说明
* 1	定义一个Person类
* 2	定义一个Policeman类,继承Person类
* 3	定义一个Superman类,继承Policeman类
* 4	定义一个demo泛型方法,该方法接收一个Array参数,
* 5	限定demo方法的Array元素类型只能是Person、Policeman
* 6	测试调用demo,传入不同元素类型的Array
*/
object Demo40_3_2 {
 // 1	定义一个Person类
 class Person
 // 2	定义一个Policeman类,继承Person类
 class Policeman extends Person
 // 3	定义一个Superman类,继承Policeman类
 class Superman extends Policeman
 // 4	定义一个demo泛型方法,该方法接收一个Array参数,
 // 5	限定demo方法的Array元素类型只能是Person、Policeman
 def demo[T >: Policeman](arr:Array[T])=arr.foreach(println(_))

 def main(args: Array[String]): Unit = {
   // 6	测试调用demo,传入不同元素类型的Array
   demo(Array(new Person,new Policeman))
   //下面的会编译报错,因为Superman不符合要求
   //demo(Array(new Superman))
 }
}

40.4 协变、逆变、非变

package com.ithe.scala

/**
*40.4 协变、逆变、非变
* 如何让带有泛型的类支持类型转换呢?
*/
object Demo40_4 {
 class Pair[T](a: T)

 object Pair {
   def main(args: Array[String]): Unit = {
     val s1: String = "hello"
     //可以将String类型转换成AnyRef类型
     val s2: AnyRef = s1

     //定义一个Pair[String]类型的实例
     val p1:Pair[String] = new Pair("hello")
     //编译报错,无法将p1:Pair[String]转换成Pair[AnyRef]
     //val p2: Pair[AnyRef] = p1
     //为什么String类型可以转换成AnyRef类型,但是Pair[String]不能转换成Pair[AnyRef]类型?,怎样才能转?
   }
 }
}

40.4.1 非变

40.4.2 协变

40.4.3 逆变

package com.ithe.scala

/**
* 40.4.1 非变
* 40.4.2 协变
* 40.4.3 逆变
* 示例
* 示例说明
* 1	定义一个Super类、以及一个Sub类继承自Super类
* 2	使用非变、协变、逆变分别定义三个泛型类Temp1、Temp2、Temp3
* 3	分别创建泛型类来演示非变、协变、逆变
*/
object Demo40_4_1and2and3 {

 // 1	定义一个Super类、以及一个Sub类继承自Super类
 class Super
 class Sub extends Super

 // 2	使用非变、协变、逆变分别定义三个泛型类Temp1、Temp2、Temp3
 //非变
 class Temp1[T]
 //协变
 class Temp2[+T]
 //逆变
 class Temp3[-T]

 // 3	分别创建泛型类来演示非变、协变、逆变
 def main(args: Array[String]): Unit = {
   //非变
   val a: Temp1[Sub] = new Temp1[Sub]
   //编译报错
   //val b:Temp1[Super] = a

   //协变,子类Sub可以转换为父类Super,那么Temp2[Sub]也可以转换成Temp2[Super]
   val c = new Temp2[Sub]
   val d: Temp2[Super] = c
   //逆变,子类Sub可以转换为父类Super,那么反过来,Temp2[Super]可以转换成Temp2[Sub]
   val e = new Temp3[Super]
   val f: Temp3[Sub] = e

 }
}

  1. Actor
    41.1 Actor介绍
    41.1.1 Java并发编程的问题
/**

**/

41.1.2 Actor并发编程模型

/**

**/

41.1.3 Java并发编程对比Actor并发编程

/**

**/

41.2 创建Actor
41.2.1 使用方式

package com.ithe.scala

import scala.actors.Actor

/**
* 41.2 创建Actor
* 41.2.1 使用方式
* 示例
* 示例说明
* 创建两个Actor,一个Actor打印1-10,另一个Actor打印11-20
* 1	使用class继承Actor创建(如果需要在程序中创建多个相同的Actor)
* 2	使用object继承Actor创建(如果在程序中只创建一个Actor)
*/
object Demo41_2_1 {
 // 创建两个Actor,一个Actor打印1-10,另一个Actor打印11-20
 // 1	使用class继承Actor创建(如果需要在程序中创建多个相同的Actor)
 class Actor1 extends Actor{
   override def act(): Unit = {(1 to 10).foreach(println(_))}
 }
 class Actor2 extends Actor{
   override def act(): Unit = {(11 to 20).foreach(println(_))}
 }
 // 2	使用object继承Actor创建(如果在程序中只创建一个Actor)
 object Actor3 extends Actor{
   override def act(): Unit = {(1 to 10).foreach(println(_))}
 }
 object Actor4 extends Actor{
   override def act(): Unit = {(11 to 20).foreach(println(_))}
 }
 def main(args: Array[String]): Unit = {
   val actor1 = new Actor1
   val actor2 = new Actor2
   actor1.start()
   actor2.start()

   Thread.sleep(2000)
   println("\n\n\n"+"-"*15+"\n\n\n")

   Actor3.start()
   Actor4.start()

 }
}

41.2.1 Actor程序运行流程

/**

**/

41.3 发送消息/接收消息
41.3.1 使用方式

package com.ithe.scala

import scala.actors.Actor

/**
* 41.3 发送消息/接收消息
* 41.3.1 使用方式
* 示例
* 示例说明
* 1	创建两个Actor(ActorSender、ActorReceiver)
* 2	ActorSender发送一个异步字符串消息给ActorReceiver
* 3	ActorReceive接收到该消息后,打印出来
*/
object Demo41_3_1 {
 // 1	创建两个Actor(ActorSender、ActorReceiver)
 // 2	ActorSender发送一个异步字符串消息给ActorReceiver
 object ActorSender extends Actor{
   override def act(): Unit = {
     ActorReceiver ! "你好。"
     //下面这句,ActorReceiver收不到。
     ActorReceiver ! "你叫什么名字?"
   }
 }
 // 3	ActorReceive接收到该消息后,打印出来
 object ActorReceiver extends Actor{
   override def act(): Unit = {
     receive{
       case msg:String => println(s"收到了ActorSender的消息: $msg")
     }
   }
 }

 def main(args: Array[String]): Unit = {
   //启动ActorSender
   ActorSender.start()
   //启动ActorReceiver
   ActorReceiver.start()
 }
}

41.4 持续接收消息

package com.ithe.scala

import java.util.concurrent.TimeUnit

import scala.actors.Actor

/**
* 41.4 持续接收消息
* 上述代码,ActorReceiver无法接收到ActorSender发送的第二条消息。
* 我们希望ActorReceiver能够一直接收消息,怎么实现呢?
* ——我们只需要使用一个while(true)循环,不停地调用receive来接收消息就可以啦。
* 示例
* 示例说明
*   	在上一个案例的基础上,让ActorReceiver能够一直接收消息
*/
object Demo41_4 {
 object ActorSender extends Actor{
   override def act(): Unit = {
     //持续发送消息
     while (true){
       ActorReceiver ! "hello"
       TimeUnit.SECONDS.sleep(1)
     }
   }
 }
 object ActorReceiver extends Actor{
   override def act(): Unit = {
     //持续接收消息
     while (true){
       receive{
         case msg:String => println(s"接收到消息:$msg")
       }
     }
   }
 }

 def main(args: Array[String]): Unit = {
   ActorSender.start()
   ActorReceiver.start()
 }
}

41.5 使用loop和react优化接收消息

package com.ithe.scala
import scala.actors.Actor
import scala.actors.threadpool.TimeUnit
/**
* 41.5 使用loop和react优化接收消息
* 示例
* 示例说明
* 使用loop + react重写上述案例
*/
object Demo41_5 {
 object ActorSender extends Actor{
   override def act(): Unit = {
     //持续发送消息
     while (true){
       ActorReceiver ! "hello"
       TimeUnit.SECONDS.sleep(1)
     }
   }
 }
 object ActorReceiver extends Actor{
   override def act(): Unit = {
     //使用loop + react持续接收消息
     loop{
       react{
         case msg:String => println(s"接收到消息:$msg")
       }
     }
   }
 }

 def main(args: Array[String]): Unit = {
   ActorSender.start()
   ActorReceiver.start()
 }
}

41.6 发送和接收自定义消息

package com.ithe.scala

import scala.actors.Actor

/**
* 41.6 发送和接收自定义消息
* 示例一
* 示例说明
* 1 定义发送消息样例类该消息包含两个字段(message, company)
* 2 定义MsgActor,他可以接收并打印消息
* 3 启动MsgActor
* 4 main线程向MsgActor发送一个异步无返回消息
*/
object Demo41_6_1 {
 //1 定义发送消息样例类该消息包含两个字段(id、message)
 case class Message(message:String,company:String)
 //2 定义MsgActor,他可以接收并打印消息
 object MsgActor extends Actor{
   override def act(): Unit = {
     receive{
       case Message(message,company) => println(s"收到的消息是:$message $company")
     }
   }
 }

 def main(args: Array[String]): Unit = {
   //3 启动MsgActor
   MsgActor.start()
   //4 main线程向MsgActor发送一个异步无返回消息
   MsgActor ! Message("交话费了","中国移动")
 }

}

package com.ithe.scala

import scala.actors.Actor

/**
* 41.6 发送和接收自定义消息
* 示例二
* 示例说明
* 1 定义发送消息样例类该消息包含两个字段(id、message)和回复消息样例类包含两个字段(message、name)
* 2 定义MsgActor,他可以接收消息,并回复一个消息
* 3 启动MsgActor
* 4 main线程向MsgActor发送一个同步消息,并等待接收回复的消息
* 5 将回复的消息转换成精确的类型
* 6 打印回复消息
*/
object Demo41_6_2 {
 //1 定义发送消息样例类该消息包含两个字段(id、message)和回复消息样例类包含两个字段(message、name)
 case class Message(id:Int,message:String)
 case class ReplyMessage(message:String,name:String)

 // 2	定义MsgActor,他可以接收消息,并回复一个消息
 object MsgActor extends Actor{
   override def act(): Unit = {
     //接收消息
     receive{
       case Message(id,message) => {
         println(s"接收到了消息,发送人是【$sender】,接收的内容是【${Message(id,message)}】")
         //回复一个消息
         sender ! ReplyMessage("收到了","tom")
       }
     }
   }
 }

 def main(args: Array[String]): Unit = {
   // 3	启动MsgActor
   MsgActor.start()
   //4main线程向MsgActor发送一个同步消息,并同步等待接收回复的消息
   val reply: Any = MsgActor !? Message(1,"你好")
   //5将回复的消息转换成精确的类型
   val replyMessage = reply.asInstanceOf[ReplyMessage]
   // 6	打印回复消息
   println(replyMessage)
 }

}

package com.ithe.scala

import scala.actors.{Actor, Future}

/**
*41.6 发送和接收自定义消息
*  示例三
* 示例说明
* 1 定义发送消息样例类该消息包含两个字段(id、message)和回复消息样例类包含两个字段(message、name)
* 2 定义MsgActor,他可以接收消息,并回复一个消息
* 3 启动MsgActor
* 4 main线程向MsgActor发送一个异步有返回消息,并异步接收回复的消息
* 5 将回复的消息转换成精确的类型
* 6 打印回复消息
*/
object Demo41_6_3 {
 //1 定义发送消息样例类该消息包含两个字段(id、message)和回复消息样例类包含两个字段(message、name)
 case class Message(id:Int,message:String)
 case class ReplyMessage(message:String,name:String)

 // 2	定义MsgActor,他可以接收消息,并回复一个消息
 object MsgActor extends Actor{
   override def act(): Unit = {
     //接收消息
     receive{
       case Message(id,message) => {
         println(s"接收到了消息,发送人是【$sender】,接收的内容是【${Message(id,message)}】")
         //回复一个消息
         sender ! ReplyMessage("收到了","tom")
       }
     }
   }
 }

 def main(args: Array[String]): Unit = {
   // 3	启动MsgActor
   MsgActor.start()
   //4main线程向MsgActor发送一个异步有返回消息,并异步接收回复的消息
   val future: Future[Any] = MsgActor !! Message(1,"你好")
   //此处future.apply()是一个阻塞等待返回结果的过程
   val reply: Any =future.apply()
   //5将回复的消息转换成精确的类型
   val replyMessage = reply.asInstanceOf[ReplyMessage]
   // 6	打印回复消息
   println(replyMessage)
 }

}

41.7 WordCount案例

/**
* 41.7 WordCount案例
* 41.7.1 获取文件列表
* 实现思路
* 新建一个wordcount包,用来存放相关代码
* 在main方法中读取指定目录(${project_root_dir}/data/)下的所有文件,并打印所有的文件名
* 实现步骤
* 1. 新建一个wordcount包
* 2.	在工程根目录下创建/data/用于测试的数据文件
* 3. 在wordcount包下新建MainActor单例对象
* 4.	加载工程根目录,获取到所有文件
* 5.	打印所有文件名
*
* 41.7.2 创建WordCountActor
* 实现思路
* 根据文件数量创建WordCountActor,为了方便后续发送消息给Actor,将每个Actor与文件名关联在一起
* 实现步骤
* 6. 定义WordCountActor类
* 7.	为每个文件关联创建一个WordCountActor实例,得到新列表。
* 8.	打印测试
*
*41.7.3 启动Actor/发送/接收任务消息
* 实现思路
* Main线程将任务发给各个WordCountActor,他们接收到消息并打印消息。
* 实现步骤
* 9.	定义一个样例类,描述单词统计的任务消息,包含文件名fileName属性。
* 10.	main线程将每个文件名封装为消息(!!方式)发送给对应的WordCountActor,并(等待)获取异步返回结果
* 11.	WordCountActor接收单词统计任务消息 ,打印接收到的消息。
*
* 41.7.4 消息统计文件单词计数
* 实现思路
* 读取文件文本,并统计出来单词的数量。例如:
* (hadoop, 3), (spark, 1)...
* 实现步骤
* 12.	读取文件内容,并转换为列表
* 13.	按照空格切割文本,并转换为一个一个的单词
* 14.
* 思路1   按单词本身进行分组,然后进行聚合统计
* 思路2
*   14.2.1.	为了方便进行计数,将单词转换为元组
*   14.2.2.	按照单词进行分组,然后再进行聚合统计
* 15.	打印聚合统计结果
*
* 41.7.5 封装单词计数结果回复给MainActor
* 实现思路
* 	将单词计数的结果封装为一个样例类消息,并发送给MainActor
* 	MainActor等待所有WordCount均已返回后获取到每个WordCountActor单词计算后的结果
* 实现步骤
* 16.	定义一个样例类封装单词计数结果
* 17.	将单词计数结果发送给MainActor
* 18.	MainActor中检测所有WordActor是否均已返回,如果均已返回,则获取并转换结果
* 19.	MainActor打印从各WordCountActor接收到的结果
*
* 41.7.6 结果合并
* 实现思路
* 对接收到的所有单词计数进行合并。
* 实现步骤
* 20.	在MainActor调用该合并方法,计算得到最终结果,并打印.需要拆分成一步一步来。
*/

41.7.MainActor.scala

package com.ithe.scala.wordcount

import java.io.File
import com.ithe.scala.wordcount.MessagePackage.{WordCountResult, WordCountTask}
import scala.actors.Future

object MainActor {

 def main(args: Array[String]): Unit = {
   //4.	加载工程根目录,获取到所有文件
   val file:File=new File("./day03/data")
   val file_arr:Array[String] = file.listFiles().map(_.toString)
   //5.	打印所有文件名
   println("5、所有的文件名为:"+file_arr.mkString(","))
   //7.	为每个文件关联创建一个WordCountActor实例,得到新列表。
   val tuple_arr: Array[(String, WordCountActor)] = file_arr.map( x =>(x , new WordCountActor))

   //8.	打印测试
   println("8、各文件和它对应的WordCountActor为:")
   tuple_arr.foreach(println(_))
   //10.	main线程将每个文件名封装为消息(!!方式)发送给对应的WordCountActor,并(等待)获取异步返回结果
   val future_arr: Array[Future[Any]] = tuple_arr.map(tuple => {
     val fileName: String = tuple._1
     val wordCountActor: WordCountActor = tuple._2
     wordCountActor.start()
     wordCountActor !! WordCountTask(fileName)
   })
   //18.	MainActor中检测所有WordActor是否均已返回,如果均已返回,则获取并转换结果
   while(future_arr.filter(!_.isSet).size>0){}
   val wordcount_arr: Array[Map[String, Int]] = future_arr.map(_.apply().asInstanceOf[WordCountResult].wordcount)
   //19.	MainActor打印从各WordCountActor接收到的结果
   println("19、MainActor接收到的所有结果:")
   wordcount_arr.foreach(println(_))

   //20.	在MainActor调用该合并方法,计算得到最终结果,并打印.需要拆分成一步一步来。
   val wordcount_final: Map[String, Int] = wordcount_arr.flatten.groupBy(_._1).map(x=>x._1->x._2.map(_._2).sum)
   println("20、MainActor聚合统计后的最终结果"+wordcount_final)
 }

}

41.7.MessagePackage.scala

package com.ithe.scala.wordcount

object MessagePackage {
 //9.	定义一个样例类,描述单词统计的任务消息,包含文件名fileName属性。
 case class WordCountTask(fileName:String)
 //16.	定义一个样例类封装单词计数结果
 case class WordCountResult(wordcount:Map[String,Int])

}

41.7.WordCountActor.scala

package com.ithe.scala.wordcount

import java.io.File

import com.ithe.scala.wordcount.MessagePackage.{WordCountResult, WordCountTask}

import scala.actors.Actor
import scala.io.Source

class WordCountActor extends Actor{
 override def act(): Unit = {
   loop{
     react{
       //11.	WordCountActor接收单词统计任务消息 ,打印接收到的消息。
       case WordCountTask(fileName) => {
         println(s"11、收到任务,需处理的文件名是$fileName")

         //41.7.4
         // 12.	读取文件内容,并转换为列表
         val ite: Iterator[String] = Source.fromFile(fileName).getLines()
         val lineList = ite.toList
         //13.	按照空格切割文本,并转换为一个一个的单词
         val words = lineList.flatMap(_.split(" "))
         //14.思路1	按单词本身进行分组,然后进行聚合统计
         val word_grouped: Map[String, List[String]] = words.groupBy(x=>x)
         val wordcount: Map[String, Int] = word_grouped.map(x=> (x._1 -> x._2.length) )
         //15.	打印聚合统计结果
         println(s"15、$fileName 对应的WordCountActor的统计结果:$wordcount")
         //17.	将单词计数结果异步发送给MainActor
         sender ! WordCountResult(wordcount)

       }
     }
   }
 }
}

  1. 高阶函数
    42.1 作为值的函数
package com.ithe.scala

/**
* 42. 高阶函数
* 42.1 作为值的函数
* 示例
* 示例说明
* 将一个整数列表中的每个元素转换为对应个数的小星星
* List(1, 2, 3...) => List(*, **, *** ...)
* 步骤
* 1.	创建一个函数,用于将数字装换为指定个数的小星星
* 2.	在main方法中创建一个列表,调用map方法,将上面的函数,传递给map方法。
* 3.	打印转换为的列表
*/
object Demo42_1 {
 //1.	创建一个函数,用于将数字装换为指定个数的小星星
 val func = (num: Int) => "*" * num

 def main(args: Array[String]): Unit = {
   //2.	在main方法中创建一个列表,调用map方法,将上面的函数,传递给map方法。
   val list = List(1,2,3,4,5)
   val list2: List[String] = list.map(func)
   //3.	打印转换为的新列表
   println(list2)

 }
}

42.2 匿名函数

package com.ithe.scala

/**
* 42.2 匿名函数
* 示例
* 使用匿名函数优化上述代码
*/
object Demo42_2 {
 def main(args: Array[String]): Unit = {
   (1 to 10).map(num => "*" * num)
   //或者写法二.因为上面num变量只使用了一次,所以可以省略变量(理解为参数也匿名,名字不重要),使用_替代参数
   //函数匿名,参数也匿名后,简写如下:
   (1 to 10).map("*" * _)
 }
}

42.3 柯里化

package com.ithe.scala

/**
* 42.3 柯里化
* 示例一
* 示例说明
* 一个大的方法,他接收多个参数列表,通过柯里化从他衍生出多个小的函数,每个小函数是单参数列表。
* 1	编写一个方法calc_method(参数1,参数2),有一个括号参数列表,接收2个数字
* 2  将上面的方法用柯里化方式再定义一次。定义接收2个括号参数列表的柯里化方法calc_method_curring(参数列表1#)(参数列表2#),方法体和上面一样。
* 3  将柯里化方法转换成函数func1(参数列表1#)(参数列表2#)
* 4  在main方法中,给函数func1的第一个参数列表传入具体对象,第二个参数列表不动,从而将其转换成接收一个参数列表的函数func2(参数列表2#)。
* 5  调用函数func2,进行计算,打印结果
* 6  将3中func1的参数列表1#传入不同的值对象,得到不同的func2,再试一次。
*/
object Demo42_3_1 {
 //1	编写一个方法calc_method(参数1,参数2),有一个括号参数列表,接收2个数字
 def calc_method(a: Int, b: Int) = 2 * a + b

 //2	将上面的方法用柯里化方式再定义一次。定义接收2个括号参数列表的柯里化方法calc_method_curring(参数列表1#)(参数列表2#),方法体和上面一样。
 def calc_method_curring(a: Int)(b: Int) = 2 * a + b

 //3  将柯里化方法转换成函数func1(参数列表1#)(参数列表2#)
 val func1 = calc_method_curring _

 def main(args: Array[String]): Unit = {
   //4  在main方法中,给函数func1的第一个参数列表传入具体对象,第二个参数列表不动,从而将其转换成接收一个参数列表的函数func2(参数列表2#)。
   val func2 = func1(2)
   //5  调用函数func2,进行计算,打印结果
   println(func2(3))
   //6  将3中func1的参数列表1#传入不同的值对象,得到不同的func2,再试一次。
   val func2_a = func1(100)
   println(func2_a(200))

 }

}

package com.ithe.scala

/**
* 42.3 柯里化
* 示例二
* 示例说明
* 一个大的方法,他接收多个参数列表,通过柯里化从他衍生出多个小的函数,每个小函数是单参数列表。
* 1	编写一个方法calc_method(参数1,参数2,参数3),有一个括号参数列表,接收3个参数,第一个参数接收一个函数对象,其余二个接收2个数字
* 2  将上面的方法转换成接收2个括号参数列表的柯里化方法calc_method_curring(参数列表1#)(参数列表2#),
*    第一个列表接收上一步骤的参数1函数,第二个列表接收2个数字,方法体和上一步骤是一样的。
* 3  将柯里化方法转换成函数func1(参数列表1#)(参数列表2#)
* 4  在main方法中,给函数func1的第一个参数列表传入具体函数对象,第二个参数列表不动,从而将其转换成接收一个参数列表的函数func2(参数列表2#)。
* 5  调用函数func2,进行计算,打印结果
* 6  将4中func1的参数列表1#传入不同的函数对象,得到不同的func2,再试一次。
*/
object Demo42_3_2 {
//1	编写一个方法calc_method(参数1,参数2,参数3),有一个括号参数列表,接收3个参数,第一个参数接收一个函数对象,其余二个接收2个数字
def calc_method(fun_calc: (Int, Int) => Int , a: Int, b: Int) = fun_calc(a, b)

//2  将上面的方法转换成接收2个括号参数列表的柯里化方法calc_method_curring(参数列表1#)(参数列表2#),
//   第一个列表接收上一步骤的参数1函数,第二个列表接收2个数字,方法体和上一步骤是一样的。
def calc_method_curring(fun_calc: (Int, Int) => Int)(a: Int, b: Int) = fun_calc(a, b)

//3  将柯里化方法转换成函数func1(参数列表1#)(参数列表2#)
val func1 = calc_method_curring _

def main(args: Array[String]): Unit = {

  //4  在main方法中,给函数func1的第一个参数列表传入具体函数对象,第二个参数列表不动,从而将其转换成接收一个参数列表的函数func2(参数列表2#)。
  //传入一个做加法的函数对象
  val func2_add = func1((x, y) => x + y)
  //5  调用函数func2,进行计算,打印结果
  println(func2_add(4, 7))
  //6  将4中func1的参数列表1#传入不同的函数对象,得到不同的func2,再试一次。
  //传入一个做减法的函数对象
  val func2_minus = func1((x, y) => x - y)
  println(func2_minus(7, 4))

}
}

42.4 闭包

package com.ithe.scala

/**
*42.4 闭包
* 示例一
* 定义一个闭包
* 定义
*/
object Demo42_4_1 {
 //定义一个变量
 val y=10
 //定义一个函数,在函数体中引用外面的变量
 val func_add = (x:Int)=>x+y


 //在main方法中调用函数
 def main(args: Array[String]): Unit = {
   println(func_add(1))
 }
}
package com.ithe.scala

/**
* 42.4 闭包
* 示例二
* 柯里化就是一个闭包
*/
object Demo42_4_2 {
 //柯里化就是一个闭包
 def add1(x:Int)(y:Int) = {
   x + y
 }
 //上述代码相当于
 def add2(x:Int) = {
   (y:Int) => x + y
 }

 //在main方法中调用函数
 def main(args: Array[String]): Unit = {
   val f=add2(1)
   println(f(7))
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值