• Spark高级


    SCALA高级

    • 类(class)

    • 抽象类(abstract class)

    • 单例对象(object)

    • 特质(trait)

    • 样例类(case class)

    ——————————————————————————————————

    ——————————————————————————————————

    1、类Class

    • 没有静态成员和方法

    • 默认构造器就是定义类的的所有语句!!!

    • 辅助构造器在主构造器其中,因为主构造器就是类的定义语句

    • 辅助构造器第一句必须调用其它构造器

    //主构造器执行类定义中的所有语句
    class Point(var xc: Int, var yc: Int) {
     var x: Int = xc //成员变量
     var y: Int = yc   //可以不写,直接使用xc|yc
     //辅助构造器
     def this() ={
       this(0, 0) //第一句必须调用其他构造器
    }
     //成员方法
     def move(dx: Int, dy: Int) ={
       x = x + dx
       y = y + dy
    }  
    }
    var p=new Point()
    p=new Point(12,11)

    2、继承&重写方法

    • extends实现类的继承

    • 子类重写父类方法必须用override关键字声明

    class WhitePoint() extends Point{
       var color="white"
       override def move(dx:Int,dy:Int)={
           x=x+dx
           y=y+dx
           println(color+"chesse move to:"+x+","+y)
      }
    }

    3、抽象类

    • 抽象类可包含抽象方法

    • 抽象类无法实例化

    • 使用"abstract"关键字修饰

    • 子类重写抽象方法时,override可选

    abstract class Shape{
    def draw():Unit
    }
    class Square extends Shape{
    //省略构造器
       //抽象方法的重写,override可省略
       override def draw:Unit={
      println("draw a square")
    }
       //省略构造器
    var shape=new Square //多态,指向子类的父类引用
    shape.draw //无参方法,省略()
    }

    4、单例对象

    • Scala的类中无法定义静态成员,即无static关键字。

    • 没有构造器,所有不能有参数

    • 使用object关键字定义单例对象,像Java一样表达类的静态成员变量、成员方法与静态代码块

    • 单例成员相当于JAVA中类的单例模式(印证于其转换为class后全都加上了static)

    • 第一次运行时执行所有代码,之后调用只能取值或函数

    • main()方法必须定义在单例对象中

    • 单例对象与同名类定义在同一文件中时形成绑定关系(伴生类)

    !!!!单例对象就是java中全是static和final的一种类!!!
    object Blah {
     println("Blah initializing...")
     def sum(l: List[Int]): Int = l.sum
    }
    test.Blah.sum(List[Int](1, 2, 3, 4, 5))

    5、伴生

    • 单例对象与同名 类 定义在同一文件中时形成伴生绑定关系

    • 伴生类与伴生对象可相互访问各自私有的成员(单例对象通过apply函数生成实例才可以访问类的成员,此时生成的就是一般的java类)

    • 伴生对象可为伴生类增加静态成员

      !!伴生就是java中的一般类,既有静态方法和成员又有普通方法和成员!!!

      通过aplly方法和unapply方法实现两者的耦合,apply方法又提供了省略new的语法糖,使用感觉更像是一体的了

    //单例对象通过apply方法返回一个伴生类的实例
    //apply方法是关键字方法,默认返回同名类的new实例
    //单例对象.apply()等价于 单例对象()

    class Student(n: String, a: Int) {
     private var name = n    //私有变量,伴生对象可以访问
     private var age = a
    }
    //伴生对象
    object Student {
     def apply(n: String, a: Int): Student = new Student(n, a)
     def main(args: Array[String]): Unit = {
       val stu=Student("Jason",9)  
       //通过伴生对象的apply()方法创建实例,省略了创建类实例时候的new Student()的new
       println(stu.name)
    }
    }

    5、特质trait(接口)

    • 特质用于在类之间共享程序接口和字段,类似Java接口

    • 特质是字段和方法的集合,可以提供字段和方法实现(!!!!可以实现!!!)

    • 类和单例对象都可以扩展特质(extends)

    • 特质不能被实例化,因此没有构造参数,类似Java接口

    • 特质使用“trait”关键字定义

    • 实现|覆盖特质中的方法使用“override“关键字,变量常量也是一样的

    demo实例

    //大部分性质与java中的接口是类似的
    //唯一不同在于trait可以实现函数或者定义变量
    trait Pet{
       val name:String
       def cry():Unit
    }
    class Dog(val name: String) extends Pet{
     override def cry()=println("wow ...")
    }
    val dog = new Dog("Harry")
    val animals = ArrayBuffer.empty[Pet]
    animals.append(dog) //多态
    animals.foreach(pet => {println(pet.name);pet.cry()}) //子类的方法

     

    6、混入特质(mix in trait)

    多重继承(trait):一个类只能有一个父类,但是可以继承多个trait

    (想想trait和java接口的关系,但是trait可以实现方法和变量,所以用的也是extends关键字,称之为混入!)

    • 既然用的是extends那么instanceof trait必然是true

    • 类的混入时构造顺序从左向右,同一父类只会被构造一次

    abstract class A {
     val message: String
    }
    class B extends A {
     val message = "I'm an instance of class B"
    }
    trait C extends A {
     def loudMessage = message.toUpperCase()
    }
    class D extends B with C //静态混入
    val d = new D
    println(d.messge)  // I'm an instance of class B
    println(d.loudMessage)  // I'M AN INSTANCE OF CLASS B

     

    7、可替换混入

    • 可替换的trait特性,一次定义,多种混入组合(必须是子类trait)

    • OTS:(继承也可以多态啦啦啦啦)

    //类必须有声明从那个特质映射
    class Drawing{
        self:Shape=>   	//Shape是特质名,self指自身
        //这句话声明将Shape特质的结构映射到本类
        //既不继承也不实现,但可以提前编写调用trait的方法和变量的语句
        //至于这些方法具体的实现,由使用时动态混入的特质决定(多态)
        //目的:trait的多态混入。
        def start():Unit=draw()
        def stop():Unit=draw()
    }
    trait Shape {//父trait
      def draw(): Unit
    }
    trait Square extends Shape {//子trait
      def draw(): Unit = println("draw a square")
    }
    trait Triangle extends Shape {//子trait
      def draw(): Unit = println("draw a triangle")
    }
    //动态混入
    (new Drawing() with Square).start()
    (new Drawing() with Triangle).start()
    

    8、选择结构

    1、Try

    解决函数可能会判处异常的问题,成功则返回值,失败则如何

    返回类型:

    • Success

    • Failure

    2、Either

    解决返回值不确定的问题,可以有两种返回值

    返回类型:

    • Left:

    • Right:

    3、Option

    解决空指针问题

    返回类型:

    • Some

    • None

    9、样例类(case class) 重点

    • 主要用于模式匹配match

    • 常用于描述不可变的值的对象,数据完全依赖构造参数

    • 构造参数默认为val常量,因此样例类默认不可变,通过模式匹配可分解出数值

    • 只关心类中的值而不在意函数方法,类似javabean

    • 自动创建伴生对象

    • 自动实现方法toString|equals|copy

    • 关键方法:

      • apply

      • unapply

    • 两个样例类“==”操作时,通过按值比较而不是按引用

    与class的区别:

    如果一个类内部存在计算和其他复杂的行为,那它应该是class

    10、模式匹配 match 重点

    !!!模式允许任何类型!!!

    • 基本模式匹配

    //基本模式匹配
    def matchTest(x: Int): String = x match {
      case 1 => "one"
      case 2 => "two"
      case _ => "many"
    }
    matchTest(3)  // many
    matchTest(1)  // one
    
    
    • 模式守卫匹配

    //模式守卫(在模式后面加上if 条件)
    def matchTest2(x: Int): String = x match {
      case i if i==1 => "one"
      case i if i==2 => "two"
      case _ => "many"
    }
    matchTest2(3)  // many
    matchTest2(1)  // one
    
    
    • 仅类型匹配

    //仅匹配类型
    def matchTest3(x: Any): String = x match {
      case x:Int => "Int"
      case x:String => "String"
      case _ => "Any"
    }
    matchTest3(3.0)  // Any
    matchTest3(1)     // Int
    
    
    • 样例类的组合匹配

    //样例类的模式匹配
    case class Student(_name:String,_age:Int) {
      var name=_name
      var age=_age
    }
    def matchTest4(x: Student)= x match {
      case Student(name,19) => println(name)
      case Student("Tom",age) => println(age)
      case Student(name,age) => println(name,age)
      case _ => println("no matches")
    }
    matchTest4(Student("Jason",19))
    matchTest4(Student("Tom",20))
    matchTest4(Student("Jimmy",20))
    
    

    11、提取器对象Object 重点

    • 对应样例类case class,相当于自定义的case class

    • 单例对象中指定unapply()方法时,称为提取器对象(Extractor Objects)

    • unapply()方法接受一个实例对象,返回最初创建它所用的参数

    • unapply()相当于数学中的反函数,根据映射结果反转映射关系求原数据

    class Student(_name:String,_age:Int) {
      var name=_name
      var age=_age
    }
    object Student{
      def apply(name: String, age: Int): Student = new Student(name, age)
      def unapply(arg: Student): Option[(String, Int)] ={
        if(arg==null) None else Some(arg.name,arg.age)  
    }
        
    def matchTest(x:Student)=x match {
        case Student(name,age) if age<=20 => println("young man")
        //自动调用unaplly方法,返回的是个Option类
        //apply是根据参数new类,很容易推理出unapply是根据对象获取参数
        case Student(name,age) if age>20 => println("old man")
    }
    matchTest(Student("Jason",19))   //res0:young man
    

     

    12、泛型

    • 泛型类

    • 泛型函数

    • 基本与java相同

    13、型变(泛型)

    • 协变

      Class demo[+T] {}  //+表示的应该是同向型变
      class b {}
      class a extends b{}
      //demo[a]是demo[b]的子类型,称之为协变
      
    • 逆变

      //与协变相反
      class demo[-T]{} //反向型变
      //demo[a]是deme[b]的父类
      
    • 类型边界

      class demo[T<:A] //泛型限定为类型A的子类,上界
      class demo[T>:A] //泛型新丁为类型A的父类,下界
      //编译期间检查,IDE不一定检查
      

    14、内部类

    • 与java内部类基本类似,但有很一点很不同:

      • scala的内部类是绑定到类的实例对象而不是类上

      • 因此同类的不同的实例对象的内部类被认为是不同的类

      • 可以认为内部类的类名是 实例hash+内部类名

    15、正则 重点

    • r插值,保留原字符串不转义(用于保留正则字符中的转义)

      r"wds"
      //w不会被scala转义成其他字符
      
    • s插值,字符串中可以使用$引用变量

      s"$JAVA_HOME"
      //输出的是/opt/jdk
      
    • "str".r 将任何一个字符串转换为Regex类的实例对象

    • API

      • 都是regex类的方法

      //findAllMatchIn() 返回所有的匹配结果(Interator【Match】)
      val regex="abc".r
          regex.findAllMatchIn("abc@qq.com").foreach(
            x=>{
              println(x.group(0),x.toString())
            }
       	)
      
      //findFirstMatchIn() 返回第一个结果,返回类型是Option[Match]
      print(regex.findFirstMatchIn("abc@qq.com").getOrElse("not matched"))
      
      //findAllIn() 返回所有匹配的结果(Interator【String】)
      regex.findAllIn("abc@qq.com1huyang@cc.com").foreach(x=>{println(x)})
      //最后一个是空
      
    • Regex类的模式匹配

      val date = """(dddd)-(dd)-(dd)""".r
      "2014-05-23" match {
          case date(_*) => println("It is a date")
      }
      "2014-05-23" match {
          case date(year, _*) => println("The year of the date is " + year) 
      } 
      "2014-05-23" match {
          case date(year, month, day) => println(year,month,day)
      }
      
      //此处regex就是个自定义的extractor提取器,返回的是regex的构造参数即各个组的值
      //g1,g2是str中的()分组
      
    • 分组demo

      //方式一 ,不推荐,太多了
      case class Log(level:String,date:String,uri:String)
      object Father{
        def main(args: Array[String]): Unit = {
          val log=
            """
              |INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31
              |INFO 2016-07-25 requestURI:/c?app=0&p=2&did=18005472&industry=469&adid=31
              |ERROR 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=32
            """.stripMargin
          val pattern="(?<level>\w+)\s(?<date>\d{4}-\d{2}-\d{2})\s[^:]+:(?<uri>.+)".r("level","date","uri")
          var logs:ListBuffer[Log]=ListBuffer[Log]()
          
            pattern.findAllMatchIn(log).foreach(x=>{
            logs+=Log(x.group("level"),x.group("date"),x.group("uri"))
          })
          logs.foreach(x=>{
            println(x.level,x.date,x.uri)
          })
        }
      }
      
      //方式二,推荐
      pattern.findAllMatchIn(log).map(x=>{
              Log(x.group("level"),x.group("date"),x.group("uri"))
          }).foreach(x=>{
            logs.append(x)
          })
      

       

    16、集成JAVA API

    • Scala无缝集成JavaAP

    import java.text.SimpleDateFormat
    import java.util.{Calendar, Date}
    val dateFmt = "yyyy-MM-dd"
    def today(): String = {
        val date = new Date
        val sdf = new SimpleDateFormat(dateFmt)
        sdf.format(date)
    }
    
  • 相关阅读:
    opencv图像直方图均衡化及其原理
    转 让FPGA替代GPU的6大顾虑,你确定不看看吗?
    算法工程师到底在干嘛
    转 经典分类网络Googlenet
    darknet是如何对数据集做预处理的
    目标检测评价指标mAP 精准率和召回率
    opencv代码片段合集
    GAN简介
    【登录测试】登录模块的测试点
    【Jmeter自学】Jmeter里的指标
  • 原文地址:https://www.cnblogs.com/whoyoung/p/11424437.html
Copyright © 2020-2023  润新知