<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是一種針對JVM將函數和面向對象技術組合在一起的編程語言。所以Scala必須要有JVM才能運行,和Python一樣,Scala也是可以面向對象和面向函數的。Scala編程語言近來抓住了很多開發者的眼球。它看起來像是一種純粹的面向對象編程語言,而又無縫地結合了命令式和函數式的編程風格。Scala的名稱表明,它還是一種高度可伸縮的語言。Scala的設計始終貫穿著一個理念:創造一種更好地支持組件的語言。Scala融匯了許多前所未有的特性,而同時又運行于JVM之上。隨著開發者對Scala的興趣日增,以及越來越多的工具支持,無疑Scala語言將成為你手上一件必不可少的工具。Spark最最源生支持的語言是Scala。Spark主要支持java、Scala、Python和R。Scala的底層協議是akka(異步消息傳遞)。

      2. Scala安裝與開發工具

        Scala版本使用Scala-2.10.x。

        JDK使用jdk-1.8。

        開發工具使用Intellij IDEA-2017.3.5。

      二、Scala數據類型

      1. 數據類型

       

        scala擁有和java一樣的數據類型,和java的數據類型的內存布局完全一致,精度也完全一致。其中比較特殊的類型有Unit,表示沒有返回值;Nothing表示沒有值,是所有類型的子類型,創建一個類就一定有一個子類是Nothing;Any是所有類型的超類;AnyRef是所有引用類型的超類;注意最大的類是Object。

        上表中列出的數據類型都是對象,也就是說scala沒有java中的原生類型。在scala是可以對數字等基礎類型調用方法的。例如數字1可以調方法,使用1.方法名。

       

       

        如上兩圖所示,可見所有類型的基類與Any。Any之后分為兩個AnyVal與AnyRef。其中AnyVal是所有數值類型的父類型,AnyRef是所有引用類型的父類型。

        與其他語言稍微有點不同的是,Scala還定義了底類型。其中Null類型是所有引用類型的底類型,及所有AnyRef的類型的空值都是Null;而Nothing是所有類型的底類型,對應Any類型;Null與Nothing都表示空。

        在基礎類型中只有String是繼承自AnyRef的,與Java,Scala中的String也是內存不可變對象,這就意味著,所有的字符串操作都會產生新的字符串。其他的基礎類型如Int等都是Scala包裝的類型,例如Int類型對應的是Scala.Int只是Scala包會被每個源文件自動引用。

        標準類庫中的Option類型用樣例類來表示拿著可能存在、也可能不存在的值。樣例子類Some包裝了某個值,例如:Some(“Fred”);而樣例對象None表示沒有值;這比使用空字符串的意圖更加清晰,比使用null來表示缺少某值的做法更加安全(避免了空指針異常)。

      2. 聲明與定義

        字段/變量的定義Scala中使用var/val 變量/不變量名稱: 類型的方式進行定義,例如

      var index1 : Int= 1
      val index2 : Int= 1

        在Scala中聲明變量也可以不聲明變量的類型。 

      • 常量的聲明 val

        使用val來聲明一個常量。與java一樣,常量一次賦值不可修改。

      val name : String="Yang"//這是完整的寫法,可以省略類型,如下所示:
      val name="Yang"
      name="Yang2"//會報錯reassignment to val
      • 變量的聲明 var
      var name : String = "Yang" //這是完整的寫法,可以省略類型,如下所示:
      //var name = "Yang" //變量或常量聲明時,類型可以省略,Scala內部機制會推斷。
      name = "Yang2"//變量的值可以修改
      • 函數的聲明 def

        使用def關鍵字來聲明函數。例如:

      object HelloScala {
        def main(args: Array[String]): Unit = {
          println(f)
        }
        val a=1
        var b=2
        def f=a*b
      }

        def f=a*b;//只是定義a*b表達式的名字,并不求值,在使用的時候求值。這里Scala已經推斷出了f函數的返回值類型了,因為ab都是Int,所以f也是Int。從控制臺可以看出這個效果:

        def f=a*b//如果寫成val f,這時會直接算出結果。這是定義函數和定義常量的區別。

      3. 字符串

      • 注釋

        單行注釋://

      • 單行字符串

        同Java

      • 多行字符串/多行注釋

        scala中還有類似于python的多行字符串表示方式(三個單引號),用三個雙引號表示分隔符,如下:

      val strs=”””
        多行字符串的第一行   多行字符串的第二行   多行字符串的第三行”””
      • S字符串

        S字符串,可以往字符串中傳變量。

        S字符串可以調用變量/常量,在字符串前面加s,在字符串中使用${變量/常量名的數學表達式},來調用變量。如圖所示,字符串之前不寫s,則原樣輸出。${變量/常量的數學表達式},如上圖所示對常量age進行計算。

      • F字符串

        傳入的參數可以進行相應的格式的轉化。例如:

        先val height = 1.7//聲明了一個一位小數的常量身高。

        println(f"$name%s is $height%.2f meters tall")//在字符串前加f使用f字符串的功能,包含了s字符串的調用變量的功能,并且在變量名后面跟%格式來格式化變量。例如%s是表示字符串,%.2f是精確到百分位。

        println(s"$name%s is $height%.2f meters tall")//如果這里使用s字符串則只能包含s字符串調用變量的功能,不能使用f字符串格式化的功能。

        println("$name%s is $height%.2f meters tall")//如果不加s也不加f則原樣輸出。 

      • R字符串

         R字符串和Python中的raw字符串是一樣的,在java中要原樣輸出一些帶\的字符,如\t、\n等需要在前面再加一個\轉義,不然就會輸出制表符、回車。比如\n就要寫成\\n,才能原樣輸出\n,但是加上raw則不需要。例如:

       

        注意r字符串的使用是在字符串前面加raw,而不是r。

      4. 懶加載

        在Scala的底層有一個延遲執行功能,其核心是利用懶加載。如下圖懶加載常量:

        對比上面兩條命令的差異,可以發現沒有lazy的命令立即執行,并將1賦給常量x。而帶有lazy的命令沒有立即執行方法體,而是在后面val a=xl時才執行了方法體的內容。

        其中lazy是一個符號,表示懶加載;{println("I'mtoolazy");1},花括號是方法體,花括號中的分號是隔開符,用于隔開兩句話,方法體的最后一行作為方法的返回值。

        如上圖所示,定義函數的效果和懶加載方式的效果一樣,只有在調用的時候才會執行方法體。

      三、Scala 函數

      1. 函數的定義

      • 函數定義的一般形式

        如上圖所示,其中def關鍵字表示開始一個函數的定義;max是函數名;小括號中的x和y表示參數列表,用逗號隔開;小括號中的參數后面的:類型表示參數的類型;參數列表之后的:類型是函數的返回值類型;等號表示要返回值,如果沒有等號和返回值類型就表示不需要返回值,或返回值類型改為Unit也表示不需要返回值;花括號中的內容是方法體,方法體的最后一行將作為函數的返回值,這里的最后一行是x或者y。

      • 函數定義的簡化形式

        省略return(實際已經簡化)。Scala中,可以不寫return,如果不寫return則自動將最后一行作為返回值,如果沒有返回值,則函數的返回類型為Unit,類似于Java中void。

        函數和變量一樣,可以推斷返回類型。所以上述函數可以簡寫成:

      def max( x : Int, y : Int) = {if(x > y) x else y}

        這里還可以進一步把方法體的花括號也省略,所以函數可以進一步簡化為:

      def max(x : Int, y : Int) = if(x>y) x else y
      • 案例一(單個參數)
      object HelloScala {
        //  定義sayMyName方法,方法需要一個參數,類型是String,默認值是Jack。方法體前面沒有等號,就相當于沒有返回值,Unit
        def sayMyName(name : String = "張三"){
          println(name)
        }
        //函數的調用需要main函數
        def main(args: Array[String]) {
          sayMyName("李四")//如果沒有使用參數sayMyName()則使用默認值張三,如果使用參數"李四",則輸出李四
        }
      }
      • 案例二(多個參數,可變參數)

        多個相同類型的參數可以使用*表示,例如(k : Int*)表示多個Int類型的參數,具體數量不確定,類似于java中的可變參數。

      object HelloScala {
        def sumMoreParameter(k : Int*)={
          var sum=0
          for(i <- k){//使用foreach(<-)來遍歷元素k
            println(i)
            sum += i
          }
          sum
        }
        def main(args: Array[String]) {
          println(sumMoreParameter(3,5,4,6))//這里傳遞的參數個數可變
        }
      }

        當然也可以定義參數個數確定的函數,如下:

      object HelloScala {
        def add(a:Int,b:Int) = a+b//省略了方法體的花括號和方法返回值類型
        def main(args: Array[String]) {
          println(add(3,6))
        }
      } 
      •  案例三(下劃線作參數)

        使用下劃線做參數名稱

      object HelloScala {
        def add(a:Int,b:Int) = a+b
        def add2 = add(_:Int,3)//調用add方法,使用下劃線是一個符號,可以不取變量名,參數的類型是Int
        def main(args: Array[String]) {
          println(add2(5))//這里的結果和add(2,5)=7是一樣的。
        }
      }

      2. 遞歸函數

        遞歸實際上就是方法自己調自己,也可以看成是遞推公式。以階乘為例:

      • 案例四(遞歸函數)
      object HelloScala {
        def fact(n: Int): Int = if (n <= 0) 1 else n * fact(n - 1)//注意這里需要寫方法的返回值類型Int,因為遞歸的方法體里面還有這個函數,所以無法對結果的類型進行推斷。
        def main(args: Array[String]) {
          println(fac(6))
        }
      }

      3. 柯里化函數

        在計算機科學中,柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數且返回結果的新函數的技術。有時需要允許他人一會在你的函數上應用一些參數,然后又應用另外的一些參數。例如一個乘法函數,在一個場景需要選擇乘數,而另一個場景需要選擇被乘數。所以柯里化函數就是將多個參數分開寫,寫在不同的小括號里,而不是在一個小括號中用逗號隔開。例如:

      • 案例五(柯里化函數)
      object HelloScala {
        def mulitply(x:Int)(y:Int) = x*y
        def main(args: Array[String]) {
          println(mulitply(2)(4))
        }
      }
      object HelloScala {
        def mulitply(x:Int)(y:Int) = x*y
        def mulitply2 = mulitply(2)_;//柯里化就是把參數可以分開來,把部分函數參數可以用下劃線來代替
        def main(args: Array[String]) {
          println(mulitply2(3))
        }
      }

      4. 匿名函數

      • 匿名函數的概念

        匿名函數就是沒有名字的函數。例如 (x : Int, y : Int) => x * y 。這里有一點要注意,如果在“=>”前加上了這個函數的返回類型,如:(x:Int, y : Int) : Int=> x * y,反而會報錯。原因是在一般情況下,Scala編譯器會自動推斷匿名函數參數的類型,所以可以省略返回類型,因為返回類型對于編譯器而言是多余的。

      • 案例六(匿名函數,聲明方式
      object HelloScala {
        val t = () => 123
        def main(args: Array[String]) {
          println(t())//直接調用t,注意要有小括號
        }
      }

        匿名函數的標識就是=>,沒有方法名,只有一個小括號(這里也沒有參數),方法體就是直接返回的123(是{123}的簡寫)。val t是將聲明的這個匿名函數對象付給了常量t。這里看上去像是多此一舉,但是因為匿名函數往往是作為參數傳給一個函數的,所以匿名函數這樣的形式很有必要。

      • 案例七(匿名函數,做函數的參數)
      object HelloScala {
        val t = ()=>123//聲明了一個匿名函數對象付給了t
        def testfunc(c : ()=>Int ){
          println(c())
          333
        }
        def main(args: Array[String]) {
          println(testfunc(t))
        }
      }

        定義testfunc方法中需要一個參數c,其類型是()=>Int,而()=>Int是匿名函數類型的定義。這個表達式是指傳進來參數需要是一個匿名函數,該匿名函數沒有參數,返回值是Int,比如t就是這樣的匿名函數。

        在testfunc中是打印,在方法體里面才真正的調用傳進來的函數;傳進來的時候只是傳進來了一個方法體,并沒有正真的調用。只有在里面有了()時才真正的調用。

        println(testfunc(t))打印的結果有兩行,第一行是123、第二行是(),因為testfunc這個方法沒有返回值。如果將函數testfunc方法體前面加個等號就能打印出方法體最后一行(返回值)333。

      • 案例八(匿名函數,有參匿名函數的聲明)
      object HelloScala {
        val b = (a:Int)=> a*2;//把一個能將傳進來的參數乘以2的匿名函數對象賦給b
        def main(args: Array[String]) {
          println(b(8))//打印的結果為16
        }
      }
      • 案例九(匿名函數,有參匿名函數做參數)
      object HelloScala {
        def testf1(t: (Int,Int)=>Int )={
          println(t(15,15));
        }
        def main(args: Array[String]) {
          testf1((a:Int,b:Int)=>{println(a*b);a*b})//打印的結果為兩行225
        }
      }

        定義的一個以有參匿名函數作為參數的函數testf1,其參數名是t,參數類型是(Int,Int)=>Int這樣的匿名函數,它需要兩個Int類型的參數經過相應的轉化,轉為一個Int類型的返回值。

        t(15,15)這方法體里才真正的調用匿名函數t,這里的參數是寫死的,即在testf1方法里才有真正的數據。但是真正對數據的操作是交給匿名函數的,這就體現了函數式編程的特點。

      5. 嵌套函數

        嵌套函數可以認為是復合函數,是def了的一個函數中又def了一個函數。 例如:

      • 案例十(嵌套函數)
      object HelloScala {
        //定義一個函數f=(x+y)*z
        def f(x:Int, y:Int ,z:Int) : Int = {
          //針對需求,要定義個兩個數相乘的函數g=a*b,相當于復合函數。
          def g(a:Int, b:Int):Int = {
            a*b
          }
          g((x+y),z)
        }
        def main(args: Array[String]) {
          println(f(2,3,5))
        }
      } 

      6. 循環函數

        和Java的類似,Scala有foreach循環。

      • 案例十一(foreach循環)
      object HelloScala {
        //定義for_test1方法,使用for循環輸出1-50的整數
        def  for_test1() : Unit = {
          //"<-"這個符號表示foreach,使用"to"則包含末尾(閉區間),如果是until則不包含(左閉右開)。這里的to是Scala內建的一個方法。
          for(i <- 1 to 50 ){ //可以從源碼看到to是RichInt類型的方法
            println(i)
          }
        }
        def main(args: Array[String]): Unit = {
          for_test1()
        }
      }
      • 案例十二(foreach循環嵌入條件判斷)
      object HelloScala {
        //打印1000以內(不含),可以被3整除的偶數。
        def  for_test2() = {
          //可以直接在for括號里面添加if過濾條件,比Java更簡潔。多個條件使用分號隔開
          for(i <- 0 until 1000 if (i % 2) == 0 ; if (i % 3) == 0 ){
            println("I: "+i)
          }
        }
        def main(args: Array[String]) {
          for_test2()
        }
      }

      7. 分支函數

        和Java的switch…case…default分支類似,Scala有match…case…case_結構。

      object HelloScala {
        def testmatch(n:Int)={
          n match {
            case 1 => {println("是1") ;n}//"=>"表示有匿名函數,如果與1匹配上就走這個方法體
            //        break;在Scala中不需要寫break,也不能寫break,Scala中沒有break關鍵字。
            case 2 => println("是2") ;n//方法體的花括號可以省略。
            case _ => println("其他") ; "others" //case _:default
          }
        }
        def main(args: Array[String]) {
          println(testmatch(1))//結果為是1 \n 1
          println(testmatch(0))//結果為其他 \n others
        }
      }
      posted @ 2018-03-16 07:07  Huidoo_Yang  閱讀(5514)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 日韩激情无码av一区二区| 性XXXX视频播放免费直播| 国产果冻豆传媒麻婆| 亚洲国产精品老熟女乱码| 通榆县| 亚洲精品色一区二区三区| 高清中文字幕国产精品| 久久精品国产99国产精品严洲| 欧洲人与动牲交α欧美精品| 久国产精品韩国三级视频| 亚洲国产成人AⅤ片在线观看| 色又黄又爽18禁免费视频| 精品国产亚洲av麻豆特色| av在线播放观看国产| 亚洲国产精品综合久久2007| 成人亚欧欧美激情在线观看| 特级精品毛片免费观看| 麻豆天美国产一区在线播放| 国产成人欧美综合在线影院| 五月婷之久久综合丝袜美腿| 亚洲午夜爱爱香蕉片| 国产尤物精品自在拍视频首页| 亚洲精品成人综合色在线| 久久亚洲av午夜福利精品一区 | 日韩少妇人妻vs中文字幕| 日韩激情一区二区三区| 四虎国产精品永久在线看| 久久精品夜夜夜夜夜久久| 久久波多野结衣av| 温宿县| 国产精品午夜福利精品| 国产欧美亚洲精品第一页在线| 免费人成网上在线观看网址| 婷婷99视频精品全部在线观看| 国产成人精品午夜福利在线观看 | 中文字幕一区二区人妻| 国产亚洲日韩av在线播放不卡| 国产极品粉嫩尤物一区二区 | 亚洲国产天堂久久综合226114| 久久精品不卡一区二区| 国产91精品一区二区亚洲|