scala(一)

 

1、Scala 簡介算法

    一、Scala語言既可用於大規模應用程序開發,也能夠用於腳本編程,2001年由Martin Odersk 開發,主要優點 速度和它的表達性。一門函數式編程語言,既有面向對象的特色,又有面向過程的特色。編程

    二、Scala與Java關係:Scala代碼須要通過編譯爲字節碼,而後交由Java虛擬機來運行,能夠任意調用就Java的代碼。因此Scala也就是JVM的一門編程語言。數組

    三、安裝Scala版本:scala-2.11.8msi; 進入cmd 下輸入scala,進入Scala編程;  scala -version 查看Scala版本網絡

2、Scala基礎編程語言

   一、Scala解釋器:進入安裝Scala目錄下——bin目錄,運行scala.bat 函數式編程

       scala解釋器也被成爲REPL(Read取值——Evalution求值——Print打印——Loop循環),會快速編譯scala代碼爲字節碼,而後交給JVM來執行。函數

      在scala>命令行內,鍵入代碼,解釋器會直接返回結果,若是沒有指定變量來存放這個值,那麼值默認名稱爲res,並且會顯示結果數據類型。oop

    例:輸入1+1,會看到res0:Int =2   spa

     內置變量:在後面還能夠繼續使用res這變量,以及它存放的值     例:「hi,」+res0,返回res2:String =hi,2命令行

      自動補全:在scala>命令行時,可使用Tab鍵進行自動補全

   二、聲明變量

        聲明常量: val result=1+1   聲明後沒法改變它的值      例:result=3(報錯)

        聲明變量:var  result=2,result=3    聲明值能夠改變引用    (建議使用val,在網絡傳輸數據時,防止被錯誤的更改)

        聲明變量時,能夠手動指定類型,也不能夠不指定,scala會根據值進行類型推斷,也能夠將多個變量放在一塊兒聲明          例:val n1,n2 = 100                   val na1,na2:String = null

   三、數據類型與操做符

       基本數據類型:ByteCharShortIntLongFloatDoubleBoolean。   (與Java不一樣的是首字母大寫) scala數據類型統一都是類,scala本身負責基本數據類型與引用類型轉換

       使用以上類型, 直接就能夠調用大量的函數, 例如, 1.toString()1.to(10) 結果是1到10 的一個集合

      類型的增強版類型: Scala使用不少增強類給數據類型增長了上百種加強的功能或函數。

     基本操做符: Scala的算術操做符與Java的算術操做符也沒有什麼區別, 好比+-*/%等, 以及&|^>><<等。

             可是, 在Scala中, 這些操做符實際上是數據類型的函數, 好比1 + 1, 能夠寫作1.+(1)

             例如, 1.to(10), 又能夠寫作1 to 10

             Scala中沒有提供++--操做符, 咱們只能使用+-, 好比counter = 1counter++是錯誤的, 必須寫作counter += 1

    四、調用函數

        除了方法以外,Scala還提供函數 ;import scala.math._ ,_是通配符,相似Java中的*

 

import scala.math._
sqrt(2)

3、控制結構、循環與函數

    一、if表達式的定義: 在Scala中, if表達式是有值的, 就是if或者else中最後一行語句返回的值。

                              例如, val age = 30; if (age > 18) 1 else 0

                                能夠將if表達式賦予一個變量, 例如, val isAdult = if (age > 18) 1 else 0

         if表達式的類型推斷: 因爲if表達式是有值的, 而ifelse子句的值類型可能不一樣,  此時Scala會自動進行推斷, 取兩個類型的公共父類型。
                             例:if(age > 18) 1 else 0, 表達式的類型是Int, 由於10都是Int 
                         

                             例:if(age > 18) "adult" else 0, 此時ifelse的值分別是StringInt, 則表達式的值是AnyAnyStringInt的公共父類型

                             若是if後面沒有跟else, 則默認else的值是Unit, 也用()表示, 相似於Java中的void或者null。  例如, val age = 12; if(age > 18) "adult"。 此時就至關於if(age > 18) "adult" else ()
       if語句放在多行中: 默認狀況下, REPL只能解釋一行語句, 可是if表達式一般須要放在多行。     可使用{}的方式, 好比如下方式, 或者使用:pastectrl+D的方式。
                             例:

if(age > 18) { "adult"
} else if(age > 12) "teenager" else "children"

 二、語句終結符、塊表達式

       默認狀況下, Scala不須要語句終結符, 默認將每一行做爲一個語句

       一行放多條語句: 若是一行要放多條語句, 則必須使用語句終結符           例如, 使用分號做爲語句終結符, var a, b, c = 0; if(a < 10) { b = b + 1; c = c + 1 }

       對於多行語句, 仍是會使用花括號的方式

      塊表達式: 塊表達式, 指的就是{}中的值, 其中能夠包含多條語句, 最後一個語句的值就 是塊表達式的返回值。 例val d= if(a>10){"a";"b"} 返回的是b

  三、輸入輸出

      printprintlnprint打印時不會加換行符, 而println打印時會加一個換行符。

      printfprintf能夠用於進行格式化      例如, printf("Hi, my name is %s, I'm %d years old.\n", "Leo", 30)
      readLine: readLine容許咱們從控制檯讀取用戶輸入的數據, 相似於Java    中的System.inScanner的做用。
     

     輸入輸出案例:

val name = readLine("Welcome to Game House. Please tell me your name: ")
print("Thanks. Then please tell me your age: ")
val age = readInt()
if(age > 18) {
printf("Hi, %s, you are %d years old, so you are legel to come here!", name, age)
} else {
printf("Sorry, boy, %s, you are only %d years old. you are illegal to come here!",
name, age)
}

 四、循環

       (1)Scala擁有與Java相同的whiledo-while循環  ,但沒有與for(初始化變量;判斷條件;更新變量)循環直接對應的對構  ,Scala中的for: for(i<-表達式),讓變量i遍歷<-右邊表達式的全部值。

              注意:for循環的變量以前並無valvar的指定,該變量的類型是集合的 元素類型。    循環變量的做用域一直持續到循環結束。
        (2)until方法返加一個不包含上限的區間   var sum =0;for(i<-0 until 10) sum+=i                 區間是0到9,不包含10

               直接遍歷 val content="hello";for(c<- content) print(c+" ")

         (3)能夠變量<-表達式的形式提供多個生成器,用分號將它們隔開    例:for(i<-1 to 3;j<- 1 to 3)print((10*i+j)+" ")

              for循環中添加過濾條件if語句,即爲守衛式。       例:for(i<-1 to 3;j<- 1 to 3 if i !=j)print((10*i+j)+" ")

         (4)在循環中使用變量    例:for(i<-1 to 3;from =4-i;j<-from to 3) print((10*i+j)+" ")

             推導式:若是for循環的循環體以yield開始,則該循環會構造出一個   集合,每次迭代生成集合中的一個值。  

                        例:for(i<- 1 to 10) yield i%3     生成Vector(1,2,0,1,2,0,1,2,0,1)
    五、(1)高級for循環 

                多重for循環: 九九乘法表

for(i <- 1 to 9; j <- 1 to 9) {
if(j == 9) {
println(i * j)
} else {
print(i * j + " ")
}
}

           if守衛: 取偶數   for(i <- 1 to 100 if i % 2 == 0) println(i)
               for推導式: 構造集合    for(i <- 1 to 10) yield i 

        (2)在代碼塊中定義包含多行語句的函數體

               單行函數:def a(name:String) =print("hello,"+name)

               若是函數體中有多行代碼, 則可使用代碼塊的方式包裹多行代碼, 代碼塊中最後一行的  返回值就是整個函數的返回值。 與Java中不一樣, 不是使用return返回值的。

              

def sum(n: Int) :Int= {
var sum = 0
for(i <- 1 to n) sum += i
sum
}

      :Int返回值的類型

       (3)函數的定義與調用

              Scala中定義函數時, 須要定義函數的函數名、 參數、 函數體

              Scala要求必須給出全部參數的類型, 可是不必定給出函數返回值的類型。    只要右側的函數體中不包含遞歸的語句, Scala就能夠本身根據右側的表達式推斷出返回類型。

def sayHello(name: String, age: Int) = {
if (age > 18) { printf("hi %s, you are a big boy\n", name); age }
else { printf("hi %s, you are a little boy\n", name); age
} s
ayHello("leo", 30)

  (4)遞歸函數與返回類型

            若是在函數體內遞歸調用函數自身, 則必須給出函數的返回類型 。   例如實現經典的斐波那契數列: 9 + 8; 8 + 7 + 7 + 6; 7 + 6 + 6 + 5 + 6 + 5 + 5 + 4; ....

def fab(n: Int): Int = {
if(n <= 2) 1
else fab(n - 1) + fab(n - 2)
}

   (5)默認參數

        Scala中, 有時咱們調用某些函數時, 不但願給出參數的具體值, 而但願使  用參數自身默認的值, 此時就定義在定義函數時使用默認參數。 若是給出的參數不夠, 則會從左往右依次應用參數。
         例:def sayHello(firstName: String, middleName: String = "William", lastName: String = "Croft") = firstName + " " + middleName + " " + lastName 
        (6)Java與Scala實現默認參數的區別

               Java:

public void sayHello(String name, int age) {
if(name == null) {
name = "defaultName"
} if
(age == 0) {
age = 18
}
} s
ayHello(null, 0)

       scala:

def sayHello(name: String, age: Int = 20) {
print("Hello, " + name + ", your age is " + age)
} s
ayHello("leo")

   (7)帶名參數

             在調用函數時, 也能夠不按照函數定義的參數順序來傳遞參數, 而是使用帶名參數的方式來 傳遞。

              sayHello(firstName = "Mick", lastName = "Nina", middleName = "Jack")
            還能夠混合使用未命名參數和帶名參數, 可是未命名參數必須排在帶名參數前面。
             sayHello("Mick", lastName = "Nina", middleName = "Jack")
       (8)使用序列調用變長參數

              在若是要將一個已有的序列直接調用變長參數函數, 是不對的。 好比val s = sum(1 to 5)此時須要使用Scala特殊的語法將參數定義爲序列, 讓Scala解釋器可以識別。
              val s = sum(1 to 5: _*) 經過 :_*轉換成參數序列
            例:使用遞歸函數實現累加

 

def sum2(nums: Int*): Int = {
if (nums.length == 0) 0
else nums.head + sum2(nums.tail: _*)
}

          Int* :變長參數(參數長度可變)      head取出集合第一個元素     tail 取出第一個剩下的元素

   六、函數——過程、 lazy值和異常

             過程:Scala中, 定義函數時, 若是函數體直接包裹在了花括號裏面, 而沒有使用=鏈接,  則函數的返回值類型就是Unit, 這樣的函數就被稱之爲過程。  過程一般用於不須要返回值的函數。
 過程還有一種寫法, 就是將函數的返回值類型定義爲Unit
                     例:def sayHello(name: String) = "Hello, " + name
                          def sayHello(name: String) { print("Hello, " + name); "Hello, " + name }
                          def sayHello(name: String): Unit = "Hello, " + name

             lazy:Scala中, 提供了lazy值的特性, 也就是說, 若是將一個變量聲明爲lazy, 則只有在第一次使用  該變量時, 變量對應的表達式纔會發生計算。 這種特性對於特別耗時的計算操做特別有用,

好比打開文件進行IO, 進行網絡IO等。 

                    import scala.io.Source._
                    lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
                   即便文件不存在, 也不會報錯, 只有第一次使用變量時會報錯, 證實了表達式計算的lazy特性。

                   val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString 與lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString的比較

                    lazy聲明的這行代碼並無被執行,當調用lines時才被執行,lazy是spark scala中很重要的特性

          異常:Scala中, 異常處理和捕獲機制與Java是很是類似的。

                例:

try {
throw new IllegalArgumentException("x should not be negative")
} catch {
case _: IllegalArgumentException => println("Illegal Argument!")
} finally {
print("release resources!")
}

  或者

try {
throw new IOException("user defined exception")
} catch {
case e1: IllegalArgumentException => println("illegal argument")
case e2: IOException => println("io exception")
}

4、數組

     一、數組

        若長度固定使用Array,若長度不固定則使用ArrayBuffer

         定長數組  val nums=new Array[Int](10); //10個整數的數組      或者    val str =Array("hello","world")

         String 默認值是null   Int默認值0  Boolean 默認值 是false   ,取值時 數組用(),JAVA用[]

     二、變長數組:數組緩衝

          對於那種長度按須要變化的數組,JavaArrayListScala有 ArrayBuffer 

         例:val arr=ArrayBuffer[Int]()                 先導入包 scala.collection.mutable.ArrayBuffer

               arr +=1                           添加元素

               arr++=Array(5,3,2)          添加元素

               arr.trimEnd(5)                刪除從後往前數5個

               arr.insert(2,6)              第一個表明索引,剩下爲添加的元素(在第三個數前添加6)

               arr.remove(2,3)           第一個表明索引,第二個是個數(移除三個數,從第三個開始依次日後)

     三、變長數組與定長數組之間的轉換

          變長數組→定長數組:.toArray                 定長數組→變長數組:.toBuffer        對原數組沒有影響,只是構建新的集合

     四、遍歷數組

           for(i<-0 until arr.length) print(arr(i)+" ")

           for(i<-(0 until arr.length).reverse)  print(arr(i)+" ")        數組中的元素從後往前依次輸出

           for (i<-0 until (arr.length,2)) print(arr(i)+" ")              跳躍輸出,長度爲2,例:原數組  (1,2,3,4,5)   結果(1,3,5)

      五、數組經常使用算法

           arr.sum    求和                   arr.max   求最大值          arr.min  最小值

           val  arrs=arr.sorted    對arr數組進行排序     

           val  arrs=arr.sortWith(_>_)        降序排序

           val  arrs=arr.sortwith(_<_)        升序排序

            arrs.mkString("and")       arrs.mkString("&&")    mkString方法容許指定元素之間的分隔符

 5、補充
     
一、接口在scala中不存在, 函數存在不依賴類,方法依賴於類
       二、實現直接三角形

for(i<-1 to 5;temp=2*i-1;j<-1 to temp){
print("*")
if(j==temp)println()
}

  三、遞歸函數:自身調用自身       

def fn(n:Int):Int{
if(n>0&&n<=1) 1
else n*fn(n-1)
}

  四、十進制轉換成二進制

         十進制6轉換成二進制,6除以2等3餘0 ,3除以2等1餘1,1除以2等0餘1,因此轉換成二進制是 00000110 (總共8位,餘數倒着來)

     五、面向對象三大特性

相關文章
相關標籤/搜索