• Scala零基础教学【41-60】


    第41讲:List继承体系实现内幕和方法操作源码揭秘

      def main(args: Array[String]) {
        /**
          * List继承体系实现内幕和方法操作源码揭秘
          *
          * List本身是一个抽象类 定义如下:
          * abstract sealed class List[+A] extends AbstractSeq[A]
          * with LinearSeq[A]
          * with Product
          * with GenericTraversableTemplate[A, List]
          * with LinearSeqOptimized[A, List[A]]
          *
          * List下的两个重要的子类Nil和::
          * Nil 表示一个空值  定义为一个Cass Object:  case object Nil extends List[Nothing]
          * :: 定义 final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B]
          *
          */
        //这种方式其实是 调用List的伴生对象的apply方法  val list: List[Int]
        val list: List[Int] = List(1, 2, 3, 4, 5)
        //这是一种"协变"的概念  Int为Any的子类  所以认为List[Int]的具体父类型可以是List[Any]
        val listAny: List[Any] = list
        println(list.isEmpty)
        println(list.head)
        println(list.tail)
        println(list.length)
        println(list.drop(2))
        list.map(_ * 2)
    
      }
    

      

     第42讲:Scala中泛型类、泛型函数、泛型在Spark中的广泛应用

    /**
      * 定义一个泛型类[]中定义的就是未知的类型 只有赋值使用才能确定具体的类型
      */
    class Triple[F, S, T](val first: F, val second: S, val third: T)
    
    /**
      * Scala中泛型类、泛型函数、泛型在Spark中的广泛应用
      */
    object Hello_Type_Parameterization {
    
      def main(args: Array[String]) {
        //在定义后scala的类型推断会得出triple类型为 Triple[String, Int, Double]
        val triple = new Triple("Spark", 3, 3.1415)
        //显示声明类型
        val bigData = new Triple[String, String, Char]("Spark", "Hadoop", 'R')
    
        //定义泛型类型
        def getData[T](list : List[T]) = list(list.length / 2)
        //List(1)=>"Hadoop"
        println(getData(List("Spark", "Hadoop", 'R')))
        val f = getData[Int] _
        println(f(List(1,2,3,4,5,6)))//5
        
        val queue = Queue(1,2,3,4,5)
        val queue_appended = queue enqueue 6
        println("queue : " + queue + "   " + "queue_appended : " + queue_appended)
        
      }
    
    }
    

     

    第43讲:Scala中类型变量Bounds代码实战及其在Spark中的应用源码解析

    /**
      * 类型的界定
      * 这里的[T <: Comparable[T]] 表示类型T必须是Comparable[T]的子类
      */
    class Pair[T <: Comparable[T]](val first : T,val second : T){
      def bigger = if(first.compareTo(second) > 0)first else second  
    }
    /**
      * [R >: T]表示 R类型是T类型的父类
      * 类型变量的界定 就R而言 T为R的下界   就T而言 R为T的上界
      *
      */
    class Pair_Lower_Bound[T](val first:T,val second:T){
      def replaceFirst[R >: T](newFirst:R)= new Pair_Lower_Bound[R](newFirst,second)
    }
    
    object Typy_Variables_Bounds {
    
      def main(args: Array[String]){
        /**
          * 49-57:0-9
          * A-Z:66-90
          * a-z:97-122
          */
        val schar='S'
        println(schar.toInt)
        println('H'.toInt)
        println("Spark".compareTo("Hadoop"))//11
        val pair = new Pair("Spark", "Hadoop")
        println(pair.bigger)//Spark
      }
    }
    

      

     第44讲:Scala中View Bounds代码实战及其在Spark中的应用源码解析

    class Pair_NotPerfect2[T <: Comparable[T]](val first : T,val second : T){
      def bigger = if(first.compareTo(second) > 0)first else second
    }
    
    /**
      * 视图界定   <%
      */
    /**
      * Ordered视图界定
      * 上面这种方式的12行first.compareTo(second) > 0 通过compareTo来比较 但是不能直观的像数学比较那样清晰
      * Scala提供了Ordered视图界定
      * Ordered在Comparable上提供一些关系型的操作符 < > <= >=等
      */
    class Pair_NotPerfect[T <% Comparable[T]](val first : T,val second : T){
    	def bigger = if(first.compareTo(second) > 0)first else second  
    }
    
    class Pair_Better[T <% Ordered[T]](val first : T,val second : T){
    	def bigger = if(first > second)first else second  
    }
    
    
    
    object View_Bounds {
    
      def main(args: Array[String]) {
    
    //    val pair2 = new Pair_NotPerfect2(1, 3)
    //    println(pair2.bigger)
        
        val pair = new Pair_NotPerfect("Spark", "Hadoop")
        println(pair.bigger)
        /*
           * 当类型界定为Pair_NotPerfect[T <: Comparable[T]]报错 因为Int本身不是Comparable的子类
           *
           * 当类型界定为视图界定时 Pair_NotPerfect[T <% Comparable[T]] 就可以正常运行
           * 是因为Int本身不是Comparable的子类型 Scala通过"隐式转换"将Int转换成RichInt 而这个类型是Comparable的子类
           */
        val pairInt = new Pair_NotPerfect(3, 5) //Int -> RichInt
        println(pairInt.bigger)
        /**
          * 注意:这样定义不是因为String的上界是Ordered[String],String不是Ordered[String]的子类
          * 当使用视图界定时 会发生"隐式转换" 把String --> RichString
          * 而RichString是Ordered[RichString]的子类型  RichString中是实现了这样的 < > <= >=等方法
          * 从而真正是让String类型完成视图界定
          */
        val pair_Better_String = new Pair_Better("Java", "Scala") //String -> RichString
        println(pair_Better_String.bigger)
    
        val pair_Better_Int = new Pair_Better(20, 12)
        println(pair_Better_Int.bigger)
    
        
      }
    
    }
    

      

    第45讲:Scala中Context Bounds代码实战及其在Spark中的应用源码解析

    /**
      * 上下文界定  [T : Ordering]  说明存在一个隐式的值Ordering[T]    //implicit ordered: Ordering[T]
      *
      * Ordering源码声明:
      * trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable
      */
    class Pair_Ordering[T : Ordering] (val first : T, val second : T){
    
      //这是一个隐式转换的显式定义 这个函数没有参数 当时函数执行的时候 这个隐式值就会自动传进来
      def bigger(implicit ordered: Ordering[T]) = {
        if (ordered.compare(first, second) > 0) first else second
      }
    }
    
    object Context_Bounds {
    
      def main(args: Array[String]) {
        
        val pair = new Pair_Ordering("Spark", "Hadoop")
        println(pair.bigger)
        
        val pairInt = new Pair_Ordering(3, 5)
        println(pairInt.bigger)
    
      }
       
    }
    

    第46讲: ClassTag 、Manifest、ClassManifest、TypeTag代码实战及其在Spark中的应用源码解析

    package com.wanji.scala.type_parameterization
    
    import scala.reflect.ClassTag
    
    
    class A[T]
    
    /**
      * ClassTag 、Manifest、ClassManifest、TypeTag代码实战及其在Spark中的应用源码解析
      *
      * ClassTag ==> ClassManifest
      * TypeTag  ==> Manifest
      */
    
    object Manifest_ClassTag {
    
      def main(args: Array[String]) {
    
        /**
          * Q: 可以创建泛型数组吗? 理论上是不可以的,因为没有指定具体的,在Scala程序运行中,数组必须有具体的类型,没有否无法创建的相应的数组
          *
          * 引出Manifest的概念可以创建泛型数组
          * [T : Manifest]这样的写法被称之为Manifest上下文界定  实质上这是需要一个Manifest[T]类型的隐式对象 这又是一个"隐式转换"的过程
          * 通过这个隐式的值来辅助构建泛型数组,来确定T的具体类型
          * 所以在创建泛型函数时 需要Manifest的类型来辅助构建泛型数组,借助Manifest类型对象来指定泛型数组具体的类型
          *
          * 通过Manifest[T]可以记录T的类型 在实际运行的时候我们获取T具体的类型
          **/
    
        def arrayMake[T: Manifest](first: T, second: T) = {
          val r = new Array[T](2)
          r(0) = first
          r(1) = second
          r
        }
    
        arrayMake(1, 2).foreach(println)
    
        /**
          * [T : ClassTag]这种写法说明 当这个函数在运行时 对存在一个ClassTag[T]一个隐式值 这种方式是最常用的
          */
        def mkArray[T: ClassTag](elems: T*) = Array[T](elems: _*)
    
        mkArray(42, 13).foreach(println)
        mkArray("Japan", "Brazil", "Germany").foreach(println)
    
        /**
          * Manifest的原生写法,不推荐
          */
        def manif[T](x: List[T])(implicit m: Manifest[T]) = {
          if (m <:< manifest[String]) //<:< 表示m是manifest[String]类型
            println("List strings")
          else
            println("Some other type")
        }
    
        manif(List("Spark", "Hadoop"))
        manif(List(1, 2))
        manif(List("Scala", 3))
        val m = manifest[A[String]]
        println(m)
        val cm = classManifest[A[String]]
        println(cm)
      }
    
    }
    

     

    第47讲:Scala多重界定代码实战及其在Spark中的应用源码解析

    class M_A[T]
    class M_B[T]
    
    /**
      * scala多重界定代码实战及其在Spark中的应用源码解析
      *
      * T<:A with B
      * T是A或者B的子类
      *
      * T>:A with B
      * A或者B是T的子类
      *
      * T>:A <:B (写法上 下界必须在前边 上届必须在后面)
      * T同时拥有下界A和上界B(A必须为B的子类型) 但是T不能同时拥有多个上界或者多个下界
      *
      * T:A:B(上下文界定)
      *
      * T <% A <% B(视图界定)  T必须能够同时转化为A和B的要求
      * T可以< 同时>拥有多个视图界定
      * T可以通过"隐式转换"为A 也可以"隐式转换"为B
      *
      */
    
    object Multiple_Bounds {
    
      def main(args: Array[String]) {
        implicit val a = new M_A[Int]
        implicit val b = new M_B[Int]
        def foo[ T : M_A : M_B ](i:T) = println("OK")
        foo(2)
        
      }
    
    }
    

      

    第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析 

    /**
      * Scala类型约束代码实战及其在Spark中的应用源码解析
      *
      * A =:= B 表示A类型等同于B类型
      * A <:< B 表示A类型是B类型的子类型
      */
    
    object Type_Contraints {
    
      def main(args: Array[String]){
    
        def rocky[T](i:T)(implicit ev: T <:< java.io.Serializable) {
          print("Life is short,you need spark!") }
          rocky("Spark")
      }
    
    }
    

     

    第49讲:Scala中Variance代码实战及其在Spark中的应用源码解析

    /**
      * Scala中Variance代码实战及其在Spark中的应用源码解析
      *
      * 通俗讲
      * B是A的子类 ==>List[B]是List[A]的子类(与具体元素的继承关系同向)  这样称之为"协变"
      * B是A的子类 ==>List[A]是List[B]的子类(与具体元素的继承关系反向)  这样称之为"逆变"
      * 如果支持上面的这种概念 就被称之为"Variance" 否则称之为"inVariance"
      *
      * 事实上Java不支持在定义一个类型时声明为这样的"Variance"
      * e.g. String是object的子类,List<String> 却不是 List<Object>的子类
      * 但是Java中是存在这样的痕迹的 比如:
      * List<? extends Object> list = new ArrayList<String>()
      * 在Scala中也是可以向上面这样写的:
      * val list: List[_ <: Any] = List[String]("Spark", "Hadoop")
      *
      * 事实上Java支持在使用的时候 可以这样去定义,在声明的时候不支持,但是Scala中的可以
      *
      * Scala中 在声明时留意表达这种Variance的关系
      * 形如class C[+T] “+”表示"协变" 也就是说若B为A的子类型 则C[B]是C[A]的子类型
      *    class C[-T] “-”表示"协变" 也就是说若B为A的子类型 则C[A]是C[B]的子类型
      *
      */
    
    class Person
    class Student extends Person
    class C[+T](val args: T)
    class S[+T](arg : T) extends C[T](arg)
    trait Friend[-T]{
      def makeFriend(somebody: T)
    }
    
    object Variance {
      def makeFriendWithYou(s: Student, f: Friend[Student]){f.makeFriend(s)}
      def main(args: Array[String]) {
        val value : C[Person] = new C[Student](new Student)
    
    //    List<? extends Oject> list = new ArrayList<String>()
        val list : List[_ <: Any] = List[String]("Spark")
      }
    
    }
    

    第50讲:Scala中Variance变化点及其在Spark中的应用源码解析

    package com.wanji.scala.type_parameterization
    
    
    //class P[+T](val first: T, val second: T)
    class P[+T](val first: T, val second: T){
    //  def replaceFirst(newFirst: T) = new P[T](newFirst, second)
      //方法是泛型的  方法的参数是逆变点 返回值是协变的协变点
      def replaceFirst[R >: T](newFirst: R) = new P[R](newFirst, second)
    }
    
    object Variant_Positions {
    
      def main(args: Array[String]) {
         
      }
    
    }
    

      

     第51讲:Scala中链式调用风格的实现代码实战及其在Spark编程中的广泛运用

    package com.wanji.scala.type_parameterization
    
    
    class Animal { def breathe:this.type=this }
    class Cat extends Animal { def eat :this.type= this }
    
    object Singleton_Types {
    
      def main(args: Array[String]): Unit = {
        /* * 代码2 报错
        * * cat.breathe 返回的是Animal的this Animal实例没有eat方法 所以报错
        * */
        /*
        * * 为了到达链式调用 采用代码1
        * * 注意:this.type = this       *
        * * Q:type是指什么?
        * * A:在Scala中 任何类对象都有一个type属性
        * * 当执行cat.breathe其实返回的Cat类实例的type 而这个type有eat方法
        * */
        val cat = new Cat
        cat.breathe.eat
      }
    
    }
    

     第52讲:Scala中路径依赖代码实战详解

       val outer = new Outer
        val inner =  new outer.Inner
    
        /**
          * Scala中的内部类 必须依赖于外部类的实例 而外部类的实例各不相同
          * 所以被之为这种对于外部类的依赖为"路径依赖"
          * 所以不同的路径代表不同的类型
          */
        val inner2: outer.Inner = new outer.Inner
        println(inner)
        println(inner2)
    
        
        val o1 = new Outer
        val o2 = new Outer
        //报错 o1与o2不是同样的实例
        //val i2: o2.Inner = new o1.Inner
        val i: Outer#Inner = new o1.Inner
        //o1.Inner是Outer#Inner的子类。外部类#内部类:类型投影(不同外部类实例,但内部类是同一类型)。
        //虽有路径依赖,但还想用Java风格就用这种表达方式。
    

      

    例如:
    有2个社交网络,facebook和twitter,有很多会员,是依赖于各自网络的。
    就算是同一个人在这两个不同的社交网络里,也是不同的实例。
    spark编程中,数据是分布式的,会分成很多的片,不同分片的数据从理论上讲是一样的(当然数据内容不同),也就是说,属于同样类型的数据,但是我们写代码时,处理数据时,还是处理属于每一个blog或split分片的结果。从这个角度看,也可看作是路径依赖。

    第53讲:Scala中结构类型实战详解

    /**
      * Scala中结构类型实战详解
      * 结构类型不关心传入的类型 只关心传入的对象具有某种行为
      */
    class Structural {
      def open()=print("A class instance Opened")
    }
    
    object Structural__Type {
    
      def main(args: Array[String]){
        init(new { def open()=println("Opened") })
    
        /**
          * type的作用是把“=”右边的内容起个别名
          */
        type X = { def open():Unit }
    
        def init(res:X) = res.open
    
        init(new { def open()=println("Opened again") })
        /**
          * 定义单例对象
          */
        object A {
          def open() {println("A single object Opened")}
        }
        init(A)
        
        val structural = new Structural
        init(structural)
        
      }
    
      /**
        * 从函数的定义来看,并不关心传入的对象为何,只关心传入的对象必须具有open方法
        *
        */
      def init( res: {def open():Unit} ) { 
                res.open 
            }
    }
    

    第54讲:Scala中复合类型实战详解

    trait Compound_Type1; 
    trait Compound_Type2;
    class Compound_Type extends Compound_Type1 with Compound_Type2
    
    object Compound_Type {
      def compound_Type(x: Compound_Type1 with Compound_Type2) = {
        println("Compound Type in global method")
      }
    
      def main(args: Array[String]) {
        
        compound_Type(new Compound_Type1 with Compound_Type2)
        object compound_Type_oject extends Compound_Type1 with Compound_Type2
        compound_Type(compound_Type_oject)
        
        type compound_Type_Alias = Compound_Type1 with Compound_Type2
        def compound_Type_Local(x:compound_Type_Alias) = println("Compound Type in local method")
        val compound_Type_Class = new Compound_Type
        compound_Type_Local(compound_Type_Class)
        
        type Scala = Compound_Type1 with Compound_Type2 { def init():Unit }
      }
    
    }
    

      

     第55讲:Scala中Infix Type实战详解

     def main(args: Array[String]) {
        
        object Log { def >>:(data:String):Log.type = { println(data); Log } }
        "Hadoop" >>: "Spark" >>: Log
        
         val list = List()
         val newList = "A" :: "B" :: list
         println(newList)
        
        class Infix_Type[A,B]
        val infix: Int Infix_Type String = null
        val infix1: Infix_Type[Int, String] = null
        
        case class Cons(first:String,second:String)
        val case_class = Cons("one", "two")
        case_class match { case "one" Cons "two" => println("Spark!!!") } //unapply
        
      }
    

      第56讲:Scala中Self Types实战详解

    /**
      * Scala中Self Types实战详解
      */
    class Self { 
        self =>  //用法一:self => 表示this的别名 这是self和this等价   注意不能使用this作为别名
        val tmp="Scala" 
        def foo = self.tmp + this.tmp
    }
    trait S1
    class S2 {
      /**
        * 用法二:
        * 这种方式和self =>并不一样  将S1比如为摸个trait是
        * 这种this:S1为this的别名时 有一个强制的要求
        * (1)在该类型实例化时 必须混入这个类型 即: val c = new S2 with S1 否则报错
        * (2)在继承该类的子类是 也必须混入 比如:class S3 extends S2 with S1 若不混入with S1则报错
        * */
    
    
      this:S1 =>
    }
    class S3 extends S2 with S1
    
    trait T { this:S1 => } 
    object S4 extends T with S1
    object Self_Types {
    
      def main(args: Array[String]) {
        class Outer { outer => 
    	    val v1 = "Spark"
    	    class Inner {
            /**
              *  用法三:
              *  这里内部类需要访问外部类成员和方法
              *  通过定义了outer =>代替了外部类Outer的this
              *  在内部类理由直接引用不需要考虑this是谁this
              *  这是使用这种方式声明的好处
              *  如果写成println(this.v1)则报错 因为这个this代表了Inner的this
              *  下面的三种写法都是正确的  */
    
            println(outer.v1)
            println(v1)
            println(Outer.this.v1)
    	    }
        }      
        val c = new S2 with S1
      }
    
    }
    

     

    第57讲:Scala中Dependency Injection实战详解

    trait Logger { 
      def log (msg : String) }
    trait Auth { 
        auth : Logger => 
        def act(msg : String) { 
            log(msg)
        }
    }  
    object DI extends Auth with Logger { 
      override def log(msg : String) = println(msg); }
    object Dependency_Injection {
    
      def main(args: Array[String]) {
        DI.act("I hope you'll like it")
      }
    
    }
    

    第58讲:Scala中Abstract Types实战详解

    import scala.io.Source
    import scala.io.BufferedSource
    
    trait Reader{
      /**
        * 用type关键字 声明一个In类型(称为"抽象类型")
        * 但是没有指明具体类型是什么类型 需要在它的实现类中指明具体的类型
        * 在声明抽象类型时 可以对类型进行限定
        */
      type In <: java.io.Serializable
      type Contents
    
      /**
        *在抽象对的可以使用抽象类型
        */
      def read(in: In): Contents
    }
    class FileReader extends Reader {
      type In = String   //实现中具体的类型
      type Contents = BufferedSource  //type Contents=Contents
      override def read(name: In)  = Source.fromFile(name)
    }
    object Abstract_Types {
    
      def main(args: Array[String]) {
        val fileReader = new FileReader
        val content = fileReader.read("F:\1.txt")
        for (line <- content.getLines){
    		  println(line)
    		}
      }
    
    }
    

      

    第59讲:Scala中隐式转换初体验实战详解以及隐式转换在Spark中的应用源码解析

    import scala.io.Source
    import java.io.File
    
    /**
      * Scala中隐式转换初体验实战详解以及隐式转换在Spark中的应用源码解析
      */
    //这里的RichFile相当于File的增强类 需要的将要增强的类作为参数传入构造器中
    class RichFile(val file:File){
       def read = Source.fromFile(file.getPath()).mkString
    }
     
    object Context{
        //File --> RichFile
        //implicit是隐式转换的关键字 这里定义一个隐式转换函数把当前类型转换成增强的类型
        implicit def file2RichFile(file:File)= new RichFile(file) //File -> RichFile
    }
    object Hello_Implicit_Conversions {
    
      def main(args: Array[String]) {
       	  import Context.file2RichFile
        //File类本身没有read方法 通过隐式转换完成
        //这里的read方法是RichFile类中的方法  需要通过隐式转换File --> RichFile
    	  println(new File("F:\1.txt").read)
      }
    }
    

     第60讲:Scala中隐式参数实战详解以及隐式参数在Spark中的应用源码解析

    /**
      * Scala中隐式参数实战详解以及隐式参数在Spark中的应用源码解析
      */
    object Context_Implicits{
        implicit val default:String = "Flink"
    }
     
    object Param{
       def print(content:String)(implicit language:String){
          println(language+":"+content)
       }
    }
    object Implicit_Parameters {
    
      def main(args: Array[String]) {
        Param.print("Spark")("Scala")
         
        import Context_Implicits._
        //隐式参数没有传值,编译器会在全局范围内搜索 有没有implicit String类型的隐式值 并传入
        Param.print("Hadoop")
      }
    }
    

      

  • 相关阅读:
    mysql联合主键自增、主键最大长度小记
    针对list集合进行分页展示
    初识javascript变量和基本数据类型
    12.19如何定义正则表达式
    人民币符号在html的显示方法
    windows下的NodeJS安装
    css 实现未知图片垂直居中
    IE678下placeholder效果,支持文本框和密码框
    jvm004 解析与分派
    jvm003 类加载的过程
  • 原文地址:https://www.cnblogs.com/sunrunzhi/p/9681487.html
Copyright © 2020-2023  润新知