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
三、數據類型與操做符
基本數據類型:Byte、 Char、 Short、 Int、 Long、 Float、 Double、 Boolean。 (與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 = 1, counter++是錯誤的, 必須寫作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表達式是有值的, 而if和else子句的值類型可能不一樣, 此時Scala會自動進行推斷, 取兩個類型的公共父類型。
例:if(age > 18) 1 else 0, 表達式的類型是Int, 由於1和0都是Int
例:if(age > 18) "adult" else 0, 此時if和else的值分別是String和Int, 則表達式的值是Any, Any是String和Int的公共父類型
若是if後面沒有跟else, 則默認else的值是Unit, 也用()表示, 相似於Java中的void或者null。 例如, val age = 12; if(age > 18) "adult"。 此時就至關於if(age > 18) "adult" else ()
將if語句放在多行中: 默認狀況下, REPL只能解釋一行語句, 可是if表達式一般須要放在多行。 可使用{}的方式, 好比如下方式, 或者使用:paste和ctrl+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
三、輸入輸出
print和println: print打印時不會加換行符, 而println打印時會加一個換行符。
printf: printf能夠用於進行格式化 例如, printf("Hi, my name is %s, I'm %d years old.\n", "Leo", 30)
readLine: readLine容許咱們從控制檯讀取用戶輸入的數據, 相似於Java 中的System.in和Scanner的做用。
輸入輸出案例:
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相同的while和do-while循環 ,但沒有與for(初始化變量;判斷條件;更新變量)循環直接對應的對構 ,Scala中的for: for(i<-表達式),讓變量i遍歷<-右邊表達式的全部值。
注意:在for循環的變量以前並無val或var的指定,該變量的類型是集合的 元素類型。 循環變量的做用域一直持續到循環結束。
(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用[]
二、變長數組:數組緩衝
對於那種長度按須要變化的數組,Java有ArrayList,Scala有 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位,餘數倒着來)
五、面向對象三大特性