Scala

Scala六大特性

1.Java和Scala可以混编
2.类型推测(自动推测类型)
3.并发和分布式(Actor)
4.特质,特征(类似java中interfaces和abstract结合)
5.模式匹配(类似java中的switch…case)
6.高阶函数
一句话总结: Scala是一门以Jvm为运行环境的静态类型编程语言,具备面向对象及函数式编程的特性。

Scala安装

  1. 下载安装包
https://www.scala-lang.org/download/all.html
  1. 配置环境变量
系统变量中: 
新建->
		变量名: SCALA_HOME
		变量值: 安装路径(bin的上级目录)
添加到Path路径: %SCALA_HOME%\bin 

CMD验证: scala -version
若显示版本: Scala code runner version 2.11.8 -- Copyright 2002-2016, LAMP/EPFL
配置成功。
  1. IDEA配置Scala
    安装Scala插件在这里插入图片描述
    新建scala项目
    在这里插入图片描述
    在这里插入图片描述
    新建Scala类
    在这里插入图片描述
    选择object类型
    在这里插入图片描述
    打印"Holle World"
    在这里插入图片描述

Scala基础

数据类型
Byte 8bit 有符号数字,范围-128~127
Short 16bit 有符号数字,范围-32768~32767
Int 32bit 有符号数字,范围-2147483648~2147483647
Long 64bit 有符号数字,范围 -92233720368554775808~9223372036854775807
Float 32bit IEEE 754 单精度浮点数
Double 64bit IEEE 754 双精度浮点数
Char 16 bit Unicode字符,范围 U+000~U+FFFF
String 字符串
Boolean 布尔类型
Any 所有类的超类
AnyRef 所有引用类型的超类
AnyVal 所有值类型的超类
Unit 表示无值,与其他语言void等同
Null 空值或空引用
Nothing 所有其他类型的子类 表示没有值

特殊的: 
None与Some是Option的两个子类,Some用于安全的函数返回值。
Scala推荐在可能返回空的方法使用Option[x]作为返回类型。如果有值就返回Some[x],否则返回None。

例:
 def get(key: A): Option[B] ={
	if (contains(key))
		Some(getValue(key))
	else
		None
}
类和对象
  1. 一行的结尾可以省略分号,如果一行中有多个语句可以使用分号隔开
  2. var修饰变量,val修饰常量
  3. class默认实现了getter setter方法
  4. class中如果有参数的传入,那么这个构造器就是这个类的默认构造器
  5. 重写构造器,必须调用类默认构造器
  6. class再被new对象的时候,除了方法内部不执行,其他地方的代码都会被执行
  7. object里面不能传递参数,object里面的属性和方法都是静态(类似java中static修饰的东西)。类似于java中的工具类。 (类名.方法)
  8. 伴生类和伴生对象: 在一个Scala文件中,如果class和Object的名字一样,则互为伴生类和伴生对象,他们可以直接访问到互相的私有成员变量
package package01

class Person(xname:String,xage:Int){

  println("啊哈哈哈哈哈~")

  {
    println("类似于静态代码块....")
  }

  private val naem = xname ;
  val age = xage ;
  var  money =100.0;
  //重写构造方法 (重写构造器,必须调用类的默认构造器)
  def this(xname:String,xage:Int,xmoney:Double){
    this(xname:String,xage:Int)
    money = xmoney
  }

  //定义一个方法
  def talk (): Unit = {
    println("走路......")
  }

}

object Person {
  def main(args: Array[String]): Unit = {
    val person = new Person(xname = "柳宗元", 56)
    println(person.naem,person.age)
    val person2 = new Person("李白", 56, 300000.0)
    println(person2.naem,person2.age,person2.money)
 }
}
键盘标准输入

import scala.io.stdIn
val a = StdIn.readxx()

to 和 until
    println(1 to 10) 
    println(1 until 10)
    println(1 to (10,2) )
    println(1 until (10,2) )
count+

scala中不能写count++ count-- 只能写count+
var a = 0
a += 1

双重for循环
 //双重for循环
    for(i <- 1 to 9 ; j <- 1 to i){
      print(i+"*"+j+"="+i*j+"\t")
      if (i==j){
        println()
      }
    }

 //双重for循环拆分版
    for(i <- 1 to 9){
      for(j <- 1 to i){
        print( i+"*"+j+"="+i*j+"\t")
        if(i==j){
          println()
        }
      }
    }
yield

将for中符合条件的元素用yield关键字返回一个集合。
(for {子句} yie1d {变量或表达式},原来的集合不会被改变,只会通过你的for/yield构建出一个新的集合。
for循环中可以加条件判断,分号隔开。

  val a = for (i <- 1 to 10 ; if(i>5) ) yield i/2
    for ( b <- a){
      println(b)
    }

Scala函数

  1. return关键字可以省略,scala自动将函数的最后一行的值作为函数的返回值
  2. {}只有一句语句时,可以省略{}
  3. 函数可以省略返回类型(显式),会进行类型自动推断(隐式)。显示调用return时不能省略返回类型。
  4. =可以省略,如果省略掉,函数会自动将返回值丢弃一般用在无返回值的函数中去省略=。
  5. 方法的参数是使用val定义的,即方法内只能使用参数而不能修改参数值。
package package01

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

      def walk(name:String): String ={
        println(name+"走路.....")
        return name
      }

    var result = walk("李白")
    println("谁在走路?----"+result)

    /* 无返回值函数
    def walk(name:String) ={
        println(name+"走路.....")
        return name
      }

    var result = walk("李白")
    println("谁在走路?----"+result)
     */
  }
}

递归函数

  1. 递归函数(自己调自己),关键点在于递归的定义,终止条件(不然会出现栈溢出问题)
  2. 递归函数不能省略方法返回值类型
package package01

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

    //递归函数(自己调自己),关键点在于递归的定义,终止条件(不然会出现栈溢出问题)
    //递归函数不能省略方法返回值类型
    def fun1(num:Int):Int={
      if(num==1){
        num
      }
      else num*fun1(num-1)
    }

    val sum = fun1(5)
    println(sum)

  }
}

包含参数默认值的函数

  1. 默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值。
  2. 如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称。
 def fun2(num1:Int=5,num2:Int=10)={
        println(num1+num2)
    }
    fun2() //5+10=15
    fun2(10) //10+10=20
    fun2(10,20) //10+20=30
    fun2(num2 = 5) //5+5=10

  }

可变参数个数的函数

Java中写法: int …a

def fun3(a:Int*)={
      var sum=0
      for (b <- a){
        sum+=b
      }
      println(sum)
    }
    fun3(1,1,1,1,6) //10

匿名函数

  1. 匿名函数(没名字的函数) 作用:和高阶函数结合使用
  2. 将匿名函数返回给val定义的值
  3. 匿名函数不能显式声明函数的返回类型
  4. ()=>{}
val a1= (a:Int,b:Int)=>{println(a+b)}
a1(5,6)
val a2= () =>{println("无参匿名函数..") }
a2()
val a3=(b:Int,c:Int)=>{b+c}
println(a3(1,2))

嵌套函数

函数里面套函数

def fun4(a:Int,b:Int)={
      def fun5(c:Int)={
        println((a+b)*c)
      }
      fun5(20)
    }
    fun4(10,20)//600

偏应用函数

偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。

  def log(data:java.util.Date,logText:String) ={
     println("时间:"+data +"\n"+"信息:"+ logText)
   }
   log(new Date(),"日志信息...")
   //偏应用函数使用效果: 时间固定,只更改日志赋值内容
   val logWriterFoinLogText = log(new Date(), _: String)
   logWriterFoinLogText("日志信息...")

高阶函数

  1. 函数的参数是函数
  2. 或者函数的返回是函数
  3. 或者函数的参数和返回都是函数
  函数的参数是函数
	def fun6(a:Int,f1:(Int,Int)=>Int)={
	  var resoult = f1(10,20)
	  println(a*resoult)
	}
	def fun7(a:Int,b:Int)={ a+b }
	fun6(10,fun7)
	//使用匿名函数实现高阶函数的参数部分
    fun6(10,(a:Int,b:Int)=>{a+b})
 高阶函数(返回类型是函数)
   def fun8(a:Int,b:Int):(String,String)=>String ={
      def fun9(c:String,d:String):String={
        "a="+a+" b="+b+" "+c+" "+d
      }
     fun9
   }
    //调用方式一
    var function = fun8(1,2)
    println(function("起", "飞"))
    //调用方式二
    println(fun8(1, 2)("K", "L"))
  高阶函数(参数跟返回值都是函数)
    def f10(f:(Int,Int)=>Int):(Int,Int)=>Int={f}
    println(f10((a:Int,b:Int) => {a + b})(10, 90)) //100

柯里化函数

柯里化–颗粒化,将参数变成颗粒散落简而言之就是将参数拆拆拆。函数柯里化基本是在做这么一件事情:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

  柯里化函数
    def fun12(a:Int,b:Int)(c:String,d:String)={
      println(a + b + c + d)
    }
    fun12(1,2)("99","88") //39988 可以理解为高阶函数的简化版

Scala字符串

    var str: String = "ajkl"
    println(str.indexOf("k"))
    println(str.indexOf(98))
    var str2 = "AJKL"
    println(str2 == str)
    println(str2.compareToIgnoreCase(str))

    StringBuilder可变字符串
    var stringBuilder =new StringBuilder
    stringBuilder.append("abc")
    stringBuilder+'e'
    stringBuilder++="jkl"
    println(stringBuilder) //abcejkl

集合

数组
   定义数组(方式一)
    val array=Array(1,2,3)
    println(array(0))
    //遍历数组
    for(x <- array){
      print(x+" ")
    }
    //foreach遍历数组
    array.foreach(x=>{print(x)})
    //上述代码简写
    array.foreach(print(_))
    //再简写
    array.foreach(print)

   定义数组(方式二)
    val array = new Array[Int](5) //创建了一个类型为int长度为5的数组
    array(1)=1
    array(2)=22
    array(4)=44
    array.foreach(print) //0122044
    println
    //定义二维数组
    val array2 = new Array[Array[Int]](2)
    //赋值二位数组
    array2(0)=Array(100,200,300,600)
    array2(1)=Array(3,2,1)
    //遍历二维数组
    array2.foreach(x=>{ x.foreach(println)})

  数组的方法实例 concat、fill....
    val array = Array(1,2,3)
    val array2 = Array(4,5,6)
    val arraySum: Array[Int] = Array.concat(array,array2) //合并数组
    arraySum.foreach(println)
    val array3: Array[String] = Array.fill(2)("元素") //返回数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。
    array3.foreach(print)
    val array4: Array[Array[String]] = Array.fill(3,2)("二维元素") //返回二维数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。
    array4.foreach(x=>{x.foreach(print)})

   可变长度数组
    var arrayBuffer = ArrayBuffer[String]("a","b","c","...")
    arrayBuffer.append("d","e","f") //添加元素
    arrayBuffer.+=("end") //在数组最后位置添加元素
    arrayBuffer.+=:("start") //在数组开头处添加元素
    arrayBuffer.foreach(print) //startabc...defend
List
   List
    var list = List(1, 2, 3)
    list.foreach(print)
    
List方法举例  filter:过滤元素 
             count:计算符合条件的元素个数 
             map:对元素操作 
             flatmap:压扁,先map再flat

   filter过滤元素
    var list2 = list.filter(x => {
      if (x > 2)
        true
      else
        false
    })
    list2.foreach(print) //3
   count计算符合条件的元素个数
    var i = list.count(x => {
      if (x > 0) true
      else false
    })
    println('\n'+"符合条件的个数: "+i)
   map map是将一个东西变成另一个东西,映射
    var list3 = list.map(x=>{ x*10 })
    list3.foreach(print)
   map map永远一进一出
    var list4 = List("hello beijing","hello shanghai","hello hangzhou")
    var list5: Seq[Array[String]] = list4.map(x=>{ /*切割后,系统自动将它按组存进了数组*/
      x.split(" ")
    })
    list5.foreach(x=>{x.foreach(x=>{println(x)})})
    
   flatmap 1进多出 (flatmap:压扁,先map再flat) 
    var list6: Seq[String] =list4.flatMap(x=>{ x.split(" ")})
    list6.foreach(x=>{println(x)})
   可变长度List
    var listBuffer = ListBuffer[Int](1,2,3,3,6,5,7)
    listBuffer.append(9,8) //添加任意个数元素
    listBuffer.+=(999) //添加到最后位置
    listBuffer.+=:(888)//添加到开头位置
    listBuffer.foreach(print)

import scala.collection.mutable.ListBuffer
Set
   Set 去重、无序集合
    var set = Set(1,2,3,3,4,4,5,5)
    set.foreach(print) //51234
   常用方法举例
    var set2 = Set(2,9,8)
    val set3 = set.union(set2) //并集
    set3.foreach(print)
    
    println
    val set4 = set.diff(set2) //差集 set &~ set2
    set4.foreach(print)
    
    println
    val set5 = set.intersect(set2) //交集 set & set2
    set5.foreach(print)

	println(set.max) //Max
    println(set.min) //Min
    val list: List[Int] = set.toList //转变为List类型的集合
    val array: Array[Int] = set.toArray //转变为数组
    val string1: String = set.mkString //将集合元素合成一组字符串
    val string2: String = set.mkString(",") //将集合元素合成一组字符串中间插入指定字符
   可变长度Set
    需要手动声明import scala.collection.mutable.Set,set集合长度默认是有限制的,若声明了便默认变成了无限制
    var set100 = Set[Int](1,2,3,4,5,100000)
    set100.add(99999)
    set100.+=(666,444,7777)
    set100.foreach(println)
Map
   Map 键值对形式集合
    val map1 = Map("name" -> "李白", "性别" -> "男", "爱好" -> "发酒疯", ("Money", 200000))
  遍历Map
    map1.foreach(println) //遍历键值对
    map1.foreach(x=>{ println(x._1+" "+x._2)}) //遍历Map中的内容
  根据指定key获取value
    val value1 = map1.getOrElse("name", "没有相应的值") //getOrElse指定key获取value时,如果没有指定的key,则返回函数的第二个参数
    println(value1)
    val value2 = map1.getOrElse("name2", "没有相应的值")
    println(value2)
 根据Key遍历Map
    val keys: Iterable[String] = map1.keys
    keys.foreach(x=>{ println(x+" "+map1.get(x).get)})
    val keySet: collection.Set[String] = map1.keySet
    keySet.foreach(println)
 遍历value
    val values: Iterable[Any] = map1.values
    values.foreach(println)
 合并Map  相同Key值对应的value值会发生覆盖。
    val map2 = Map("name" -> "陈独秀", "性别" -> "男", "爱好" -> "到处跑", ("Money2", 10000))
    val map3: Map[String, Any] = map1.++(map2)
    map3.foreach(x=>{ println( x._1+":"+x._2 ) })

常用方法举例

 filter 过滤
    var map4 = Map("鸭子"->16,("小鸡",30),("鳄鱼",45))
    val filter_map = map4.filter(x => {
      if (x._2 > 20)
        true
      else
        false
    })
    filter_map.foreach(x=>{ println(x._1+":"+x._2) })
 count 计数
    val result: Int = map4.count(x => {
      if (x._2 > 10)
        true
      else
        false
    })
    println(result)
 contains 判断Map中指定Key值是否存在
    val bool: Boolean = map4.contains("恐龙")
    println(bool)
 exists 是否存在
    val bool2: Boolean = map4.exists(x => {
      if (x._2 > 5) {
        println(x._1+": "+x._2)
        true
      }
      else {
        false
      }
    })
    println(bool2)
 可变长度Map
    val map100: mutable.Map[String, Any] = Map[String, Any]("小新" -> 6, ("野原大熊", 10))
    map100.+=("哆来A梦"->1,"小白"->"3岁","胡图图"->6)
    map100.foreach(println)
    map100.-=("小新")
    map100.remove("小白")
    map100.foreach(println)
Tuple
  元组 什么都能存
    val tuple1: (List[Int], Map[String, Int]) = Tuple2(List(1, 2, 3), Map("小新" -> 5, "胡图图" -> 6))
 遍历元组 通过迭代器进行遍历
    val iterator = tuple1.productIterator
    while (iterator.hasNext){
      println(iterator.next())
    }
  获取值
    println(tuple1._1+" "+tuple1._2)
 特殊方法  swap翻转 只针对Tuple2
    println(tuple1.swap.toString())
toString
	val tuple3: (List[Int], Map[String, Int], Int) = Tuple3(List(1, 2, 3), Map("小新" -> 5, "胡图图" -> 6),999)
    println(tuple3.toString())

Trait

Trait类似为Java中的接口和抽象类的结合
注意:

  • 继承的多个trait中如果有同名的方法和属性,必须在被继承类中使用override重新定义。
  • trait中不可以传参数
package package01

object Trait_Test {
  def main(args: Array[String]): Unit = {
 //Trait类似为Java中的接口和抽象类的结合
    val people1 = new people
    people1.playing()
  }
}


trait Play{
  val name: String ="谁"
  var process = "怎么玩"
  def playing()

}

trait Read{
  val name: String ="我"
  def reading() ={
    println("开始阅读....")
  }
}

class people extends Play with Read{
  override val name: String ="蜡笔小新"
  override def playing(): Unit = {
    println(name+"开始玩耍......")
  }
}
package package01

//在一个二维坐标系中,比较两个点的位置是否相等
object Trait_Test2 {
  def main(args: Array[String]): Unit = {
    val pointer1 = new pointer(1, 2)
    val pointer2 = new pointer(2, 3)
    val bool = pointer1.isEqual(pointer2)
    val bool2 = pointer1.isNoEqual(pointer2)
    println(bool+" "+bool2)
  }
}


trait Equal{
  def isEqual(a: Any):Boolean
  def isNoEqual(a:Any)={! isEqual(a)}
}

class pointer(xx:Int,yy:Int) extends Equal{
  val x=xx
  val y=yy
  override def isEqual(a: Any): Boolean = {
      if (a.isInstanceOf[pointer]){
        val pointer = a.asInstanceOf[pointer]
        x==pointer.x && y==pointer.y
      }
    else false
  }
  
}

模式匹配 Match

概念

  • Scala提供了强大的模式匹配机制,应用也非常广泛。
  • 一个模式匹配包含了一系列备选项,每个都开始于关键字case。
  • 每个备选项都包含了一个模式及一到多个表达式。箭头符号=>隔开了模式和表达式。

注意点

  • 模式匹配不仅可以匹配值还可以匹配类型
  • 从上到下顺序匹配,如果匹配到则不再往下匹配
  • 都匹配不上时,会匹配到case_ ,相当于default
  • match的最外面的{ }可以去掉看成一个语句
 val tuple1: (Int, String, String, Int) = Tuple4(1, "k", "李世明", 999)

 def MatchTest(i:Any)={
        i match {
          case 1 => {print("与1匹配成功..");println("起飞")}
          case 888=> println("与888匹配成功..")
          case _:String => println("与Match中String匹配成功..") //根据类型匹配,则不会再匹配到"k","李世明" 建议将这种模糊匹配放在靠后的位置
          case "k" => println("与k匹配成功..")
          case "李世明" => println("与李世明匹配成功..")
          case 999 => println("与999匹配成功..")
          case _ => println("很遗憾,没有匹配的值..")
        }
    }

  遍历tuple1的同时调用MatchTest方法
    val iterator = tuple1.productIterator
    while (iterator.hasNext){
      MatchTest(iterator.next())
    }
    

偏函数PartialFunction

  • 如果一个方法中没有match只有case,这个函数可以定义成PartialFunction偏函数。
  • 偏函数定义时,不能使用括号传参,默认定义PartialFunction中传入一个值,匹配上了对应的case,返回一个值,只能匹配同种类型。
  • 一个case语句就可以理解为是一段匿名函数。
举例一: 
def paritalFunctionTest:PartialFunction[Int,String]={
    case 1 =>"壹"
    case 2 =>"贰"
    case 3 =>"叁"
    case _ =>"乄"
  }

println(paritalFunctionTest(1)) //壹

偏函数举例二:
map函数和collect函数在源码中查看区别,collect接受的参数类型是PartialFunction[A,B] ,而不是A=>B。

//     List(1,2,3,"紫") map { (i: Int) => i + 1 } //map中的匿名函数逻辑:所有int型元素加一,报红,因为元素中有字符串。
//    List(1,2,3,"紫").map{ case i:Int => i+1} //会报MatchError异常,因为偏函数只能处理同种类型 源码: def map[B, That](f : scala.Function1[A, B])
   var list1 = List(1,2,3,"紫").collect{case i:Int=> i+1}  //源码: def collect[B, That](pf : scala.PartialFunction[A, B])
   list1.foreach(println)

样例类 case class

  • 样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val ),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
  • 样例类默认帮你实现了toString , equals , copy 和 hashCode等方法。
  • 样例类可以new,也可以不用new
 样例类
case class pepole(name:String,age:Int)
var LiBai = new pepole("李白",56)
    var ChengDuXiu = new pepole("陈独秀",36)
    println(LiBai+"  "+ChengDuXiu)
val pepoles: List[pepole] = List(LiBai, ChengDuXiu)

    pepoles.foreach(x=>{
      x match {
        case pepole("李白",56) => println("I am LiBai.")
        case pepole("陈独秀",36) => println("I am ChengDuXiu.")
        case _:pepole => println("pepole.")
        case _=> println("没有匹配到值")
      }
    })

隐式转换 implicit

隐式变量

概念: 隐式转换是在Scala编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出来合适的类型。

注意点

  • 同类型的参数的隐式值只能在作用域内出现一次,同一个作用域内不能定义多个类型一样的隐式值。
  • implicit 关键字必须放在隐式参数定义的开头
  • 一个方法只有一个参数是隐式转换参数时,那么可以直接定义implicit关键字修饰的参数,调用时直接创建类型不传入参数即可。
  • 一个方法如果有多个参数,要实现部分参数的隐式转换,必须使用柯里化这种方式,隐式关键字出现在后面,只能出现一次。
 隐式值
  implicit var name = "李白"
  implicit var c=9999

 隐式参数
  def Prin(implicit x:String)={ println(x) }

  def Prin2(age:Int)(implicit name:String,count:Int)={
    println(name+" "+age+" "+count) }

  def main(args: Array[String]): Unit = {
      Prin   //李白
      Prin2(18)
  }
  
隐式函数

隐式转换函数的注意点

  1. 函数需要由implicit关键字修饰
  2. 函数只需要关注其参数(类型A)和返回类型(类型B)。代表意思A->B,这样A就能调用B中的方法。
  3. 函数名没有影响
class bird(name:String) {
  var Bname =this.name
  def fly={
    println(Bname+"Flying....")
  }
}

class Pig(Xname:String){
  var Pname=this.Xname
}

//隐式转换函数
  implicit def PigTOBird(x:Pig):bird={
    new bird(x.Pname)
  }

def main(args: Array[String]): Unit = {
    val LaoYin = new bird("老鹰")
    LaoYin.fly
    val BlackPig = new Pig("黑毛猪")
    BlackPig.fly
  }

隐式类

注意点

  1. 隐式类必须定义在类,包对象,伴生对象中。
  2. 隐式类的构造必须只有一个参数, 同一个类,包对象,伴生对象中不能出现同类型构造的隐式类。
class Rabbit(name:String){
  var Rname = this.name
}

implicit class Animal(x:Rabbit){
    def fly ={
      println(x.Rname+"Flying....")
    }
    var money=99999
  }

def main(args: Array[String]): Unit = {
    var Xrabbit = new Rabbit("小白兔")
    Xrabbit.fly
    Xrabbit.money
  }

Actor Model

概念: Actor Model 是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼。

Actor的特征

  • ActorModel 是消息传递模型,基本特征就是消息传递
  • 消息发送是异步的,非阻塞的
  • 消息一旦发送成功,不能修改
  • Actor之间传递时,接收消息的actor自己决定去检查消息,actor不是一 直等待,是异步非阻塞的

举例一:

自己给自己发消息
class QQ extends Actor{
  override def act(): Unit = {
    while(true){
      receive( {
        case  x:String => println(x)
        case _=> println("其他类型的消息...")
      } )
    }
  }
}

def main(args: Array[String]): Unit = {
    val qq = new QQ
    qq.start()
    qq ! "晚上好!"
    qq ! 666
  }

import scala.actors.Actor

举例二:

自己给别人发消息
class QQ01(qq02: QQ02) extends Actor {
  override def act(): Unit = {
      receive({
        case x:String => println("qq01"+": "+x)
        qq02 ! "你也早..."
        case _ => println("其他类型消息...")

      })
  }
}

class QQ02 extends Actor{
  override def act(): Unit = {
      receive( {
        case x:String => println("qq02"+": "+x)
        case _ => println("其他类型消息...")
      } )
  }
}

object Actor_Test2 {
  def main(args: Array[String]): Unit = {
    val qq02 = new QQ02
    val qq01 = new QQ01(qq02)
    qq01.start()
    qq02.start()
    qq01 ! "早上好"
  }
}

举例三:

相互通讯
class QQ01(qq02: QQ02) extends Actor {
  qq02 ! Message(this,"晚上去看电影吧")
  override def act(): Unit = {
    while (true){
      receive({
        case x:String => {
          println("qq02"+": "+x)
          if(x.equals("好的")){
            qq02 ! Message(this,"那真是太好了!")
          }else if(x.equals("那晚上见")){
            qq02 ! Message(this,"晚上见~")
          }else if(x.equals("like you")){
            qq02 ! Message(this,"like you too")
          }else{ qq02 ! Message(this,"拜拜了您嘞...") }
        }
      })
    }
  }
}

class QQ02 extends Actor{
  override def act(): Unit = {
    while (true){receive( {
      case x:Message => {
        val m = x.message
        println("qq01: "+m)
        val q1 = x.actor
        val str = StdIn.readLine()
        q1 ! str

      }
    } )}
  }
}

//样例类
case class Message(actor:Actor,message:String)


object Actor_Test2 {
  def main(args: Array[String]): Unit = {
    val qq02 = new QQ02
    val qq01 = new QQ01(qq02)
    qq01.start()
    qq02.start()
  }
}

效果如下:
在这里插入图片描述

Spark-wordCount

package package01
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
 * Spark-wordCount
 */

object WordCount {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setAppName("wordCount").setMaster("local") //设置任务名、运行模式
    val sparkContext = new SparkContext(conf)

    //获取数据
    val line: RDD[String] = sparkContext.textFile("wc.txt")
    //处理数据
    //val word: RDD[String] = line.flatMap(x=>{ x.split(" ") } )
    //(单词,1)
    //val pair: RDD[(String, Int)] = word.map(x=>{ (x,1) })
    //累加
    //val result: RDD[(String, Int)] = pair.reduceByKey((x, y) => x + y)
    //打印结果
    //result.foreach(println)
    line.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).foreach(println) //精简版本
    //关闭上下文环境
    sparkContext.stop()
  }
}

运行成功
...
2022-05-11 14:19:36 INFO  Executor:54 - Running task 0.0 in stage 1.0 (TID 1)
2022-05-11 14:19:36 INFO  ShuffleBlockFetcherIterator:54 - Getting 1 non-empty blocks out of 1 blocks
2022-05-11 14:19:36 INFO  ShuffleBlockFetcherIterator:54 - Started 0 remote fetches in 5 ms
(LuXun,4)
(ChengDuXiu,5)
(hello,14)
(LiBai,5)
2022-05-11 14:19:36 INFO  Executor:54 - Finished task 0.0 in stage 1.0 (TID 1). 1095 bytes result sent to driver
2022-05-11 14:19:36 INFO  TaskSetManager:54 - Finished task 0.0 in stage 1.0 (TID 1) in 41 ms on localhost (executor driver) (1/1)
2022-05-11 14:19:36 INFO  TaskSchedulerImpl:54 - Removed TaskSet 1.0, whose tasks have all completed, from pool 
2022-05-11 14:19:36 INFO  DAGScheduler:54 - ResultStage 1 (foreach at WordCount.scala:25) finished in 0.053 s
...
处理的数据 
wc.txt

hello LiBai
hello ChengDuXiu
hello LuXun
hello LiBai
hello ChengDuXiu
hello LuXun
hello LiBai
hello ChengDuXiu
hello LuXun
hello LiBai
hello ChengDuXiu
hello LuXun
hello LiBai
hello ChengDuXiu
报过的异常
Exception in thread "main" java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V
	at org.apache.spark.SparkConf$DeprecatedConfig.<init>(SparkConf.scala:784)
	at org.apache.spark.SparkConf$.<init>(SparkConf.scala:605)
	at org.apache.spark.SparkConf$.<clinit>(SparkConf.scala)
	at org.apache.spark.SparkConf.set(SparkConf.scala:94)
	at org.apache.spark.SparkConf.set(SparkConf.scala:83)
	at org.apache.spark.SparkConf.setAppName(SparkConf.scala:120)
	at package01.WordCount$.main(WordCount.scala:13)
	at package01.WordCount.main(WordCount.scala)

该异常是因为Scala与Spark依赖包版本不兼容。
解决方案: 
	因为使用scala-2.11.8编写的程序可
    将spark-3.0.0-bin-hadoop3.2.tgz 替换为spark-2.3.1-bin-hadoop2.6.tgz。 将tgz文件解压后,将jars目录中的文件导入项目。
   
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值