<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Scala編程快速入門系列(二)

      目    錄

      一、Scala概述

      二、Scala數據類型

      三、Scala函數

      四、Scala集合

      五、Scala伴生對象

      六、Scala trait

      七、Actor

      八、隱式轉換與隱式參數

      九、Scala JDBC

      由于整理的篇幅較長,所以文章計劃分三次發布。第一部分的內容請轉至系列(一)

      四、Scala集合

      1. Scala集合概述

        Scala對集合的操作就是Spark程序的實現方式。Spark中有一個RDD(Resilience彈性的、Distributed分布式、DataSet數據集),spark的程序都是將源數據加載過來變成一個RDD,然后每一步操作都是集合的元素進行操作。對于Spark來說是分布式的操作,但是對于寫程序來說無需考慮分布式,只需考慮對集合元素的操作。Scala的集合操作是針對單機的,Spark是針對分布式的,但是代碼都類似。

      2. List集合

        這里舉例創建集合和獲取集合元素的同時也有一些常用的集合操作函數。

      • 創建List集合

         在Scala中創建一個集合不需要new關鍵字。

      object TestCollection {
        val list =List(1,4,6,4,1)
      }
      • 獲取集合的元素
      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          println("獲取集合的第2個元素:"+list(1))//集合的下標從0開始
        }
      }

        使用list(),括號中傳入集合元素的位置來獲取集合元素。 

      • map函數

        map函數的本質就是使用匿名函數對集合中每一個元素做同樣的操作。

      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          val b= list.map(a=>{println(a+"-----");a+1})
          val c= list.map(_+1)
          println(b)
          println(c)
        }
      }

        list.map是集合list調用map方法,map方法對集合的每個元素進行操作,具體的操作由匿名函數定義。第一個map函數中的a代表集合List的每一個元素,作為匿名函數的參數,執行方法體打印,然后返回最后一行a+2賦給新的集合相應位置的元素。

        list.map(_+1))//這樣寫是上式的簡寫形式,下劃線代表集合的每一個元素。

      • "+:"和":+"函數向集合添加元素
      object TestCollection {
        val list =List(1,4,6,4,1)
        val list2=list.+:("楊輝三角")
        val list3=list.:+("楊輝三角")
        def main(args: Array[String]): Unit = {
          println(list2)
          println(list3)
        }
      }

        +: 在集合第一個位置添加元素;:+ 在集合最后一個位置添加元素。運行結果如下:

        List(楊輝三角, 1, 4, 6, 4, 1)
        List(1, 4, 6, 4, 1, 楊輝三角) 

      • foreach函數遍歷輸出

        foreach和map很相似,都是對集合的每一個元素做相應的操作,只是map會返回值給集合。如果要打印結果一般用foreach。

      object TestCollection {
        val list =List(1,4,6,4,1)
        val list2=list.+:("楊輝三角")
        def main(args: Array[String]): Unit = {
          list2.foreach(i => print("---"+i))//是對集合list2中的每一個元素遍歷,i表示集合中的每一個元素。
          list2.foreach(i => {val j = i + "s"; print("---"+ j)})//可以對集合中的元素先進行有關操作
          list2.foreach(print _)//對集合遍歷輸出可以簡化為此式
        }
      }
      • distinct函數去重
      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          list.distinct.foreach(print _)
        }
      }

        輸出結果為:146

      • slice函數截取集合

         slice函數需要兩個參數,第一個參數表示從該下標開始截取,第二個參數表示截取到該下標(不包含)。

      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          print(list.slice(0,3))
        }
      }

        結果為:List(1, 4, 6)

      • for循環遍歷集合
      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          for(i <- list){
            print(i)
          }
        }
      }
      • length函數獲取集合長度
      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          for(i <- 0.to(list.length-1)){
            print(list(i))
          }
        }
      }
      • "/:"函數
      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]) {
          //list./:是調用./方法,它是一個柯里化函數,其中(100)是第一個參數,({(sum,num)=>print(sum+"--"+num+" ");sum-num})是第二個參數。
          println(list./:(100)({
            (sum,num)=>print(sum+"--"+num+" ");//函數/:的第二個參數——匿名函數需要兩個參數,匿名函數第一個參數為/:函數的第一個參數,匿名函數的返回值類型和/:函數的第一個參數類型一致
              sum+num//這里的匿名函數實際上是(sum,num)=>sum-num,就是傳入兩個參數sum和num,返回sum+num,返回值的類型顯然和sum的類型一樣。/:方法詳見源碼解讀。
          }));//返回結果為100--1 101--4 105--6 111--4 115--1 116
        }
      }
      //源碼片段:
      def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
      
      def foldLeft[B](z: B)(op: (B, A) => B): B = {
        var result = z
        this foreach (x => result = op(result, x))
        result
      }

        源碼解讀:如下代碼是/:函數的源碼,可見/:是個柯里化函數。其中,[B]是函數/:的泛型;(z: B)是第一個參數,其類型為泛型[B];(op: (B, A) => B)是第二個參數,它是一個匿名函數op,它需要兩個參數(B, A),能返回B類型的值。最后的:B是函數/:的返回值類型。/:(z)(op)=foldLeft(z)(op)。

        再看foldLeft函數,也是一個柯里化函數,需要兩個參數,參數類型和/:的參數類型一致。其方法體可見,首先將傳入的第一個B類型的參數z賦值給變量result,然后調用該方法的當前對象(如集合List對象)使用foreach(這里的this foreach和this.foreach是一樣的道理)方法遍歷當前對象中的所有元素,其元素x的類型就是匿名函數的第二個參數的類型A,這里調用匿名函數op,以result和x為參數,其返回結果賦值給result,通過多次調用匿名函數循環集合的所有元素,最后返回result,作為函數foldLeft的返回值,也就是函數/:的返回值。

      • reduce函數

         reduce函數和/:函數很類似,使用的頻率很高。

      object TestCollection {
        val list =List(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          //reduce函數,需要一個匿名函數做參數,此匿名函數的類型是(A1,A1)=>A1,匿名函數第一次的參數是前兩個元素;之后,第一個參數上一次的匿名函數返回值,第二個參數是依次位置的集合元素值。
          println(list.reduce((a: Int, b: Int) =>{println(a + "---" + b) ; a+b}))//最終結果是所有元素的和16
          //上式求所有元素的和和以簡化為下面的形式
          println(list.reduce(_+_))
        }
      }
      //源碼片段:
      def reduce[A1 >: A](op: (A1, A1) => A1): A1 = reduceLeft(op)
      def reduceLeft[B >: A](op: (B, A) => B): B = {
        if (isEmpty)
          throw new UnsupportedOperationException("empty.reduceLeft")
      
        var first = true
        var acc: B = 0.asInstanceOf[B]
      
        for (x <- self) {
          if (first) {
            acc = x
            first = false
          }
          else acc = op(acc, x)
        }
        acc
      }

        源碼解讀:reduce函數最終是要調用reduceLeft函數,顧名思義是需要從左側開始。reduceLeft函數需要一個匿名函數(op: (B, A) => B),返回類型是B,和傳入的第一個參數一樣。if (isEmpty)如果集合為空,拋出異常。0.asInstanceOf[B],B是一個泛型,0是int類型,0.asInstanceOf[B]意為將0轉為B這個泛型類型。在else acc = op(acc, x)中才開始調用傳入的匿名函數op。 

      3. Tuple元組

      • 創建元組

        在Scala中創建元組不需要關鍵字,只需要括號就行。它的特點是,定義了元組之后,元組的值不可以修改(和Python一致)。

      object TestCollection {
        val tuple =(1,4,6,4,1)
      }
      • 獲取元組元素
      object TestCollection {
        val tuple =(1,4,6,4,1)
        def main(args: Array[String]): Unit = {
          println(tuple._1)//元組取值是用"._",不能像list集合一樣用括號
          println(tuple._5)//Tuple元組下標從1開始。
        }
      } 

      4. Map集合

        Scala中的Map有兩種類型,一個是Mutable可以更改的,另一個是Immutable不可更改的。如果沒有導包直接寫Map的話是默認為Immutable的,如果要創建可以更改key的value值的Map集合需要導包,指定是Mutable的Map。

      • 創建Map集合
      object TestCollection {
        //定義一個map集合,[String,Int]分別是鍵和值的泛型。
        var map = Map[String, Int]("a" -> 1, "b" -> 2);//使用“->”來定義一對key value,每對key/value使用逗號隔開。
        var map2 = Map[String, Int](("a", 3), ("b", 4));//也可以使用(key,value)的形式定義一對key/value,因為Map中的每一個元素都是一個元組。
      }
      • 獲取集合元素
      object TestCollection {
        var map = Map[String, Int]("a" -> 1, "b" -> 2);
        def main(args: Array[String]) {
          println(map("a"));//使用(鍵)來獲取對應的值
        }
      }
      • "+="函數添加集合元素
      object TestCollection {
        var map = Map[String, Int]("a" -> 1, "b" -> 2);
        map += ("c" -> 3)
        map += Tuple2.apply("d",4)
        def main(args: Array[String]) {
          println(map);//輸出結果為Map(a -> 1, b -> 2, c -> 3, d -> 4)
        }
      }
      • foreach函數遍歷集合
      object TestCollection {
        var map = Map[String, Int]("a" -> 1, "b" -> 2);
        def main(args: Array[String]) {
          map.foreach(kv=>{
            println(kv+" "+kv._1+" "+kv._2)//這里的kv是集合m1的每一個元素,它是一組鍵值對,在Scala中是一個元組,所以要取得每一個元素的鍵和值可以使用元組的取值方法,kv._1獲得kv的鍵,kv._2獲得kv的值。
          })//其結果為(a,1) a 1\n(b,2) b 2
        }
      }
      • keys迭代器
      object TestCollection {
        var map = Map[String, Int]("a" -> 1, "b" -> 2);
        def main(args: Array[String]): Unit = {
          map.keys.foreach(k => println(map(k)))//map.keys獲得map的所有keys,返回一個迭代器;然后可以使用foreach遍歷,也可以在通過鍵獲取值。
        }
      }

      五、Scala伴生對象

      1. 伴生對象的概念

        所謂伴生,就是在語言層面上,把static成員和非static成員用不同的表達方式,class(非靜態成員)和object(靜態成員),但雙方具有相同的包名和命名(class_name和object_name可以完全一樣),編譯器會把他們編譯到一起。編譯會生成.class文件,編譯時會把名稱相同的class非靜態的和object靜態的編譯到一起。

      2. Object&Class

      • 案例一
      class Test{
        var field = "field" //類的屬性
        def doSomeThing = println("do something")//類的方法,調用需要new 對象后才可以調用
      }
      
      object Test{
        val a = "a string" //伴生對象的屬性
        def printAString = println(a)//這個方法是靜態的,可以使用Test.printString來調用。
      }

        編譯這個文件,同樣生成兩個class,一個TEST.class和一個Test$.class,這個Test$.class叫做虛構類。

      • 案例二(靜態方法和屬性)
      class TestObject {
        val str = "Good!"
        def func() = {
          println("Hello World!");
        }
      }
      
      object TestObject {
        val str= 100;
        val single = new TestObject();
        def func() = {//定義在object里是靜態方法
          println("Hello Scala!");
        }
        /**
          * main函數是static的,main函數如果定義在class中會當做普通函數,函數名為main而已。
          */
        def main(args: Array[String]) {
          //創建class的實例需要用new關鍵字
          val t1 = new TestObject();
          println(t1.str);//調用實例的str屬性
          t1.func();//調用實例的func01函數
      
          TestObject.func();//Object名.靜態方法名。
          println(TestObject.str);//Object名.靜態屬性名。
        }
      }

        執行結果如下:

      Good!
      Hello World!
      Hello Scala!
      100
      • 案例三(構造器)
      class TestConstructor(val a: Int, val b: Int) {//class類后面的小括號,是默認的構造器
        var x = a;//把參數a和b賦給變量
        var y = b;
      
        def this(xArg: Int) { //this也是構造器,在方法體里面要調用默認的構造器。
          this(xArg, 123);
          println("I'm this constructor");
        }
      }
      
      object TestConstructor {//這個對象是伴生著這個類出來的,所以叫伴生對象
        def main(args: Array[String]) {
          val p1 = new TestConstructor(321);//使用 this(xArg: Int)構造器
          println(p1.x)//321
          println(p1.y)//123
          val p2 = new TestConstructor(222, 333);//使用Point(val x: Int, val y: Int)構造器
          println(p2.x)//222
          println(p2.y)//333
        }
      }

      六、Scala trait

        trait可以認為是一種特性,但是不等同于Java中的接口,因為Java接口中沒有實現的方法,train可以有實現了的方法(方法體),trait的作用在于提取封裝共性,供各種類型的類共同使用。用法詳見下面例子:

      trait Listen {//和java的接口很像,但是不能new trait名。
        val name: String //定義變量name
        def listen() = {
          println( name + " is listening")
        }
      }
      trait Read {
        val name: String
        def read() = {
          println(name + " is reading")
        }
      }
      trait Speak {
        val name: String
        def speak() = {
          println(name + " is speaking.")
        }
      }
      class Human(val name: String) {//默認構造器需要一個屬性:名字
        def speak() = {//方法
          println("Look, "+name + " is speaking.")
        }
      }
      class Animal(val name: String) {}//創建一個動物類,構造器也是一個參數名字。
      //extends繼承Animal類。Dog(override val name: String),重寫name;with關鍵字可以加上trait特性。和Java中的繼承類,實現接口類似。
      class Dog(override val name: String) extends Animal(name: String) with Speak with Listen with Read {
        //重寫一個方法只需在方法def前面加關鍵字override。
        override def toString(): String = "Hello, My name is " + name + "! "
      }
      object TestTrait {
        def main(args: Array[String]) {
          //創建Human類的對象,命名為張三。hi調用Human類的speak方法。
          val h1 = new Human("張三")
          h1.speak()
          //創建Dog對象,調用了trait中listen方法和speak方法。
          val dog = new Dog("八公")
          dog.listen()
          dog.speak()
          //調用Dog類重寫了的toString方法。
          println(dog)
        }
      }
      posted @ 2018-03-17 07:10  Huidoo_Yang  閱讀(4015)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 水蜜桃视频在线观看免费18| 久久精品国产88精品久久| 久久婷婷大香萑太香蕉av人| 日韩一区二区三区精品区| 国产精品无码一区二区桃花视频| 欧美成人精品手机在线| 樱花影院电视剧免费| 久久亚洲精精品中文字幕| 最近中文字幕国产精品| 亚洲欧美日韩在线码| 国产熟睡乱子伦午夜视频| 国产精品青青在线观看爽香蕉| 久久久久无码精品国产h动漫| 在线成人精品国产区免费| 国产精品久久国产精麻豆| 东京热人妻无码一区二区av| 国产一区二区三区自拍视频| 人妻伦理在线一二三区| 欧美肥老太牲交大战| 三原县| 久久国产精品老女人| 免费人成视频在线| 国产成人一区二区不卡| 日本美女性亚洲精品黄色| 在线天堂最新版资源| 久热这里只有精品视频3| 午夜国产精品福利一二| 顶级欧美熟妇xx| 国精品无码一区二区三区左线| 国产成人a在线观看视频免费| 乱中年女人伦av二区| 欧美和黑人xxxx猛交视频| 99久久er热在这里只有精品99| 仪陇县| 精品人妻伦一二三区久久aaa片| 4399理论片午午伦夜理片| 无码激情亚洲一区| 亚洲最大av一区二区| 午夜福利看片在线观看| 在线视频中文字幕二区| 三明市|