scala 入门3
样例类:
样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),而且它会自动生成apply方法,允许我们快速地创建样例类实例对象。后面,在并发编程和spark、flink这些框架也都会经常使用它。
case class Abc(var a1:String, var a2:Int)
方法:
  toString
  equals
  hashCode
  copy
样例对象
      case object Abc
1. 样例类可以使用类名(参数1, 参数2)快速创建实例对象
2. 定义样例类成员变量时,可以指定var类型,表示可变。默认是不可变的
3. 样例类自动生成了toString、equals、hashCode、copy方法
4. 样例对象没有主构造器,可以使用样例对象来创建枚举、或者标识一类没有任何数据的消息
简单匹配
val result = name match {
    case "1" => s"a"
    case "2" => s"b"
    case "3" => s"c"
    case _ => s"none"
}
守卫
a match {
    case a if a >= 0 && a <= 1 => a  = 1
    case a if a > 1 && a < 2 => a  = 2
    case _ => a = 3
}
匹配类型
 value match {
      case x: Int => println("Int " + x)
      case y: Double => println("Double " + y)
      case z: String => println("String " + z)
      case _ => throw new Exception("not match exception")
    }
匹配集合
val arr = Array(1, 3, 5)
arr match {
    case Array(1, x, y) => println(x + " " + y)
    case Array(0) => println("only 0")
    case Array(0, _*) => println("0 ...")
    case _ => println("something else")
}
匹配列表
val lst = List(3, -1)
lst match {
    case 0 :: Nil => println("only 0")
    case x :: y :: Nil => println(s"x: $x y: $y")
    case 0 :: tail => println("0 ...")
    case _ => println("something else")
}
匹配元组
val tup = (1, 3, 7)
tup match {
    case (1, x, y) => println(s"1, $x , $y")
    case (_, z, 5) => println(z)
    case  _ => println("else")
}
变量声明中的模式匹配
val arr = Range(0, 10).toArray
 
// 使用模式匹配,获取第二个、第三个、第四个元素的值
val Array(_, x, y, z, _*) = arr
println(s"x=$x, y=$y, z=$z, ")
获取List中的数据
val list = Range(0, 10).toList
// 匹配列表的第一个、第二个元素的值
val x::y::tail = list
println(s"x=$x, y=$y")
匹配样例类(使用@符号分隔case语句,用来获取用于匹配的整个示例对象)
list(2) match {
	case  obj @ SubmitTask(id, name) => println(s"id=$id, name=$name");println(s"样例类:$obj")
    case HeartBeat(time) => println(s"time=$time")
    case CheckTimeOutTask => println("检查超时")
}
Option类型
Some(x):表示实际的值
None:表示没有值
getOrElse方法,当Option对应的实例是None时,可以指定一个默认值,从而避免空指针异常
偏函数:在花括号内没有match的一组case语句是一个偏函数(偏函数是一个参数和一个返回值的函数)
val list = List(1,2,3,4,5,6,7)
val list2 = list.filter{
    case x if x % 2 == 0 => true
    case _ => false
}
println(list2)
正则表达式
val regEx = """正则表达式""".r
val emailRE = """.+@(.+)\..+""".r
val emailList = List("1@qq.com", "2@gmail.com", "3@163.com", "4.com")
val size = emailRE.findAllMatchIn(emailList(0)).size
println(size)
异常
捕获异常
try {
    // 代码
}
catch {
    case ex:异常类型1 => // 代码
    case ex:异常类型2 => // 代码
}
finally {
    // 代码
}
抛出异常
throw new Exception("这是一个异常")
样例类自动实现了apply、unapply方法(可以使用scalap反编译一个样例类的字节码)
class Student {
  var name:String = _   // 姓名
  var age:Int = _       // 年龄
  
  // 实现一个辅助构造器
  def this(name:String, age:Int) = {
    this()
    
    this.name = name
    this.age = age
  }
}
object Student {
  def apply(name:String, age:Int): Student = new Student(name, age)
  // 实现一个解构器
  def unapply(arg: Student): Option[(String, Int)] = Some((arg.name, arg.age))
}
object extractor_DEMO {
  def main(args: Array[String]): Unit = {
    val zhangsan = Student("张三", 20)
    zhangsan match {
      case Student(name, age) => println(s"姓名:$name 年龄:$age")
      case _ => println("未匹配")
    }
  }
}
泛型
类和特质、方法都可以支持泛型。
泛型方法
	def getMiddle[A](arr:Array[A]) = arr(arr.length / 2)
	println(getMiddle[Int](arr1))
 
泛型类
 
	class Pair[T, S](val first: T, val second: S) 
case class Person(var name:String, val age:Int)
    val p1 = new Pair[String, Int]("张三", 10)
    val p2 = new Pair[String, String]("张三", "1988-02-19")
    val p3 = new Pair[Person, Person](Person("张三", 20), Person("李四", 30))
	
使用`<: 类型名`表示给类型添加一个上界,表示泛型参数必须要从上界继承。
U >: T 表示U必须是类型T的父类或本身
S <: T 表示S必须是类型T的子类或本身
协变、逆变、非变
协变: class Pair[+T],这种情况是协变。类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型
逆变: class Pair[-T],这种情况是逆变。类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型
非变: 类型B是A的子类型,Pair[A]和Pair[B]没有任何从属关系
Actor介绍
Actor并发编程模型,是一种基于事件模型的并发机制。Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。
创建Actor的方式和Java中创建线程很类似。下面是具体的步骤:
1. 定义class或object继承Actor特质
2. 重写act方法
3. 调用Actor的start方法执行Actor
Actor的执行顺序
1. 调用start()方法启动Actor
2. 自动执行act()方法
3. 向Actor发送消息
4. act方法执行完成后,程序会调用exit()方法
  !   发送异步消息,没有返回值           
  !?   发送同步消息,等待返回值           
  !!   发送异步消息,返回值是Future[Any]
1. 使用!、!?、!!来发送消息
2. actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数
    scala
   {
       case 变量名1:消息类型1 => 业务处理1,
       case 变量名2:消息类型2 => 业务处理2,
       ...
   }
    
3. receive方法只接收一次消息,接收完后结束Actor
在scala中,可以使用loop + react来复用线程。比while + receive更高效
1. 在编写Actor程序时,一般使用样例类来封装消息
2. 在Actor的act方法中,可以使用sender来获取发送方Actor的引用
3. Future表示发送有返回的异步消息的封装,虽然获取到了Future的返回值,但Future中不一定有值,因为可能在将来的某一时刻才会返回消息
4. 使用Future的isSet()可以检查是否已经收到返回消息,使用apply()方法可以获取返回的消息。
5. 使用TimeUnit.SECONDS.sleep来让Actor对应的线程睡眠阻塞
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号